mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
drm-misc-next for v7.2-rc1:
UAPI Changes: - amdxdna: Revert read-only user-pointer BO mappings. - panthor: Add eviction and reclaim info to fdinfo. Cross-subsystem Changes: - Convert DMA-buf system and cma heap allocators to module. Core Changes: - Cleanup driver misuses of drm/exec. Driver Changes: - Add LG LP129WT232166, AM-1280800W8TZQW-T00H, NEC NL6448BC33-70C, Riverdi RVT70HSLNWCA0 and RVT101HVLNWC00 panels. - Add support for RZ/T2H SoC to renesas. - Add cursor plane support to verisilicon. - Support DVI outputs in ite-it66121 bridge. - Assorted bugfixes, docbook updates and improvements to ivpu, tegra, host1x, nouveau. - Add DSC quirk for ASUS DC301 USB-C dock. - Use drm client buffer for tegra framebuffer. - Add support for GA100 to nouveau. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEuXvWqAysSYEJGuVH/lWMcqZwE8MFAmoYjNIACgkQ/lWMcqZw E8MtBhAAkNrVkJcjZY+i6bl7IF4QyByDf+3Yo3momVM7mYaaLDkmhlX3KDL/a9xI 5by1hm2D8+K4t7AsoWDk3oMhVD/kVU7UzuwYlFx/r3F2NUG/EF+oLJCIvL+a+kwH FH76iL9cGdqi5X76iHuZ7lbSvQv7dJbOL8EhZsbJxoKN6DHYeFDueRKckJtO1cfZ qWLLzkHQ9DsjkvDRzMN81VpXWhBRvAcFw9ZV2A+cgy8ZoOzjlQx+ytFHJt9iYWD7 FYJPMwmUR1vhYVeO1JXwRijcnYM16qkj76CoXfpOpJkIzyKgR6BrTRosDntH3xAj PHY1yKgJ8ulXsw8rmPguIPtKtRRTLYkcJh9/dYpAMjVNPPuA7HJ5+F+7TCGii8wb JSP2P0X7OZKWqko5BBX5HStTxEUmpLfFYGfRauvr5sycfEyO850rJMBaEcW16w6Y sBfDcKcgV0icU95HFEuzrT50UWb6YhYguFdRrPTa+owtubNWqa7zpRtIDolyECHh Vbg0Tzwa2iPHbempmBply9xt6PbP0Kg2yS3JZh2uGNNjS+AqvijqhzXE3qZ0eDy8 xmgNcHqeRIQkaUs3y+arCWIfQuBtXkmTkBOztwqYeDhroeqZMGsKGO9XWThC89Sc ujroH5TjQnX0KcRgFCWNuFyEUBj+ifkI/e4KaZmKTgeXe1e18oU= =9KcG -----END PGP SIGNATURE----- Merge tag 'drm-misc-next-2026-05-28' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next drm-misc-next for v7.2-rc1: UAPI Changes: - amdxdna: Revert read-only user-pointer BO mappings. - panthor: Add eviction and reclaim info to fdinfo. Cross-subsystem Changes: - Convert DMA-buf system and cma heap allocators to module. Core Changes: - Cleanup driver misuses of drm/exec. Driver Changes: - Add LG LP129WT232166, AM-1280800W8TZQW-T00H, NEC NL6448BC33-70C, Riverdi RVT70HSLNWCA0 and RVT101HVLNWC00 panels. - Add support for RZ/T2H SoC to renesas. - Add cursor plane support to verisilicon. - Support DVI outputs in ite-it66121 bridge. - Assorted bugfixes, docbook updates and improvements to ivpu, tegra, host1x, nouveau. - Add DSC quirk for ASUS DC301 USB-C dock. - Use drm client buffer for tegra framebuffer. - Add support for GA100 to nouveau. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patch.msgid.link/ef65f43c-becf-473c-a5cc-203fdfecd491@linux.intel.com
This commit is contained in:
commit
61cd9291ca
|
|
@ -58,6 +58,10 @@ properties:
|
|||
- hydis,hv070wx2-1e0
|
||||
# Jenson Display BL-JT60050-01A 7" WSVGA (1024x600) color TFT LCD LVDS panel
|
||||
- jenson,bl-jt60050-01a
|
||||
# Riverdi RVT101HVLNWC00 10.1" WXGA (1280x800) TFT LCD LVDS panel
|
||||
- riverdi,rvt101hvlnwc00
|
||||
# Riverdi RVT70HSLNWCA0 7.0" WSVGA (1024x600) TFT LCD LVDS panel
|
||||
- riverdi,rvt70hslnwca0
|
||||
# Samsung LTN070NL01 7.0" WSVGA (1024x600) TFT LCD LVDS panel
|
||||
- samsung,ltn070nl01
|
||||
# Samsung LTN101AL03 10.1" WXGA (800x1280) TFT LCD LVDS panel
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ properties:
|
|||
|
||||
# Ampire AM-1280800N3TZQW-T00H 10.1" WQVGA TFT LCD panel
|
||||
- ampire,am-1280800n3tzqw-t00h
|
||||
# Ampire AM-1280800W8TZQW-T00H 10.1" WXGA TFT LCD panel
|
||||
- ampire,am-1280800w8tzqw-t00h
|
||||
# Ampire AM-480272H3TMQW-T01H 4.3" WQVGA TFT LCD panel
|
||||
- ampire,am-480272h3tmqw-t01h
|
||||
# Ampire AM-800480L1TMQW-T00H 5" WVGA TFT LCD panel
|
||||
|
|
@ -234,6 +236,8 @@ properties:
|
|||
- nec,nl12880bc20-05
|
||||
# NEC LCD Technologies,Ltd. WQVGA TFT LCD panel
|
||||
- nec,nl4827hc19-05b
|
||||
# NEC LCD Technologies,Ltd. VGA TFT LCD panel
|
||||
- nec,nl6448bc33-70c
|
||||
# Netron-DY E231732 7.0" WSVGA TFT LCD panel
|
||||
- netron-dy,e231732
|
||||
# Newhaven Display International 480 x 272 TFT LCD panel
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ properties:
|
|||
- renesas,r9a07g043u-du # RZ/G2UL
|
||||
- renesas,r9a07g044-du # RZ/G2{L,LC}
|
||||
- renesas,r9a09g057-du # RZ/V2H(P)
|
||||
- renesas,r9a09g077-du # RZ/T2H
|
||||
- items:
|
||||
- enum:
|
||||
- renesas,r9a07g054-du # RZ/V2L
|
||||
|
|
@ -28,6 +29,9 @@ properties:
|
|||
- items:
|
||||
- const: renesas,r9a09g056-du # RZ/V2N
|
||||
- const: renesas,r9a09g057-du # RZ/V2H(P) fallback
|
||||
- items:
|
||||
- const: renesas,r9a09g087-du # RZ/N2H
|
||||
- const: renesas,r9a09g077-du # RZ/T2H fallback
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
@ -83,7 +87,6 @@ required:
|
|||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
- power-domains
|
||||
- ports
|
||||
- renesas,vsps
|
||||
|
|
@ -95,13 +98,16 @@ allOf:
|
|||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: renesas,r9a07g043u-du
|
||||
enum:
|
||||
- renesas,r9a07g043u-du
|
||||
- renesas,r9a09g077-du
|
||||
then:
|
||||
properties:
|
||||
ports:
|
||||
properties:
|
||||
port@0:
|
||||
description: DPI
|
||||
port@1: false
|
||||
|
||||
required:
|
||||
- port@0
|
||||
|
|
@ -137,6 +143,17 @@ allOf:
|
|||
|
||||
required:
|
||||
- port@0
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: renesas,r9a09g077-du
|
||||
then:
|
||||
properties:
|
||||
resets: false
|
||||
else:
|
||||
required:
|
||||
- resets
|
||||
|
||||
examples:
|
||||
# RZ/G2L DU
|
||||
|
|
|
|||
|
|
@ -1411,6 +1411,9 @@ CONFIG_RZ_DMAC=y
|
|||
CONFIG_TI_K3_UDMA=y
|
||||
CONFIG_TI_K3_UDMA_GLUE_LAYER=y
|
||||
CONFIG_STM32_DMA3=m
|
||||
CONFIG_DMABUF_HEAPS=y
|
||||
CONFIG_DMABUF_HEAPS_SYSTEM=m
|
||||
CONFIG_DMABUF_HEAPS_CMA=m
|
||||
CONFIG_VFIO=y
|
||||
CONFIG_VFIO_PCI=y
|
||||
CONFIG_VIRTIO_PCI=y
|
||||
|
|
|
|||
|
|
@ -75,26 +75,6 @@ static const struct dma_buf_ops amdxdna_ubuf_dmabuf_ops = {
|
|||
.release = amdxdna_ubuf_release,
|
||||
};
|
||||
|
||||
static int readonly_va_entry(struct amdxdna_drm_va_entry *va_ent)
|
||||
{
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct vm_area_struct *vma;
|
||||
int ret;
|
||||
|
||||
mmap_read_lock(mm);
|
||||
|
||||
vma = find_vma(mm, va_ent->vaddr);
|
||||
if (!vma ||
|
||||
vma->vm_start > va_ent->vaddr ||
|
||||
vma->vm_end - va_ent->vaddr < va_ent->len)
|
||||
ret = -ENOENT;
|
||||
else
|
||||
ret = vma->vm_flags & VM_WRITE ? 0 : 1;
|
||||
|
||||
mmap_read_unlock(mm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev,
|
||||
u32 num_entries, void __user *va_entries)
|
||||
{
|
||||
|
|
@ -104,7 +84,6 @@ struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev,
|
|||
struct amdxdna_ubuf_priv *ubuf;
|
||||
u32 npages, start = 0;
|
||||
struct dma_buf *dbuf;
|
||||
bool readonly = true;
|
||||
int i, ret;
|
||||
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
|
||||
|
||||
|
|
@ -143,10 +122,6 @@ struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev,
|
|||
ret = -EINVAL;
|
||||
goto free_ent;
|
||||
}
|
||||
|
||||
/* Pin pages as writable as long as not all entries are read-only. */
|
||||
if (readonly && readonly_va_entry(&va_ent[i]) != 1)
|
||||
readonly = false;
|
||||
}
|
||||
|
||||
ubuf->nr_pages = exp_info.size >> PAGE_SHIFT;
|
||||
|
|
@ -169,7 +144,7 @@ struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev,
|
|||
npages = va_ent[i].len >> PAGE_SHIFT;
|
||||
|
||||
ret = pin_user_pages_fast(va_ent[i].vaddr, npages,
|
||||
(readonly ? 0 : FOLL_WRITE) | FOLL_LONGTERM,
|
||||
FOLL_WRITE | FOLL_LONGTERM,
|
||||
&ubuf->pages[start]);
|
||||
if (ret >= 0) {
|
||||
start += ret;
|
||||
|
|
@ -186,7 +161,7 @@ struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev,
|
|||
|
||||
exp_info.ops = &amdxdna_ubuf_dmabuf_ops;
|
||||
exp_info.priv = ubuf;
|
||||
exp_info.flags = (readonly ? O_RDONLY : O_RDWR) | O_CLOEXEC;
|
||||
exp_info.flags = O_RDWR | O_CLOEXEC;
|
||||
|
||||
dbuf = dma_buf_export(&exp_info);
|
||||
if (IS_ERR(dbuf)) {
|
||||
|
|
|
|||
|
|
@ -111,7 +111,6 @@ struct ivpu_wa_table {
|
|||
bool clear_runtime_mem;
|
||||
bool interrupt_clear_with_0;
|
||||
bool disable_clock_relinquish;
|
||||
bool disable_d0i3_msg;
|
||||
bool wp0_during_power_up;
|
||||
bool disable_d0i2;
|
||||
};
|
||||
|
|
@ -220,8 +219,6 @@ extern bool ivpu_force_snoop;
|
|||
#define IVPU_TEST_MODE_FW_TEST BIT(0)
|
||||
#define IVPU_TEST_MODE_NULL_HW BIT(1)
|
||||
#define IVPU_TEST_MODE_NULL_SUBMISSION BIT(2)
|
||||
#define IVPU_TEST_MODE_D0I3_MSG_DISABLE BIT(4)
|
||||
#define IVPU_TEST_MODE_D0I3_MSG_ENABLE BIT(5)
|
||||
#define IVPU_TEST_MODE_MIP_DISABLE BIT(6)
|
||||
#define IVPU_TEST_MODE_DISABLE_TIMEOUTS BIT(8)
|
||||
#define IVPU_TEST_MODE_TURBO_ENABLE BIT(9)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2020-2025 Intel Corporation
|
||||
* Copyright (C) 2020-2026 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/firmware.h>
|
||||
|
|
@ -347,22 +347,6 @@ static void ivpu_fw_release(struct ivpu_device *vdev)
|
|||
release_firmware(vdev->fw->file);
|
||||
}
|
||||
|
||||
/* Initialize workarounds that depend on FW version */
|
||||
static void
|
||||
ivpu_fw_init_wa(struct ivpu_device *vdev)
|
||||
{
|
||||
const struct vpu_firmware_header *fw_hdr = (const void *)vdev->fw->file->data;
|
||||
|
||||
if (IVPU_FW_CHECK_API_VER_LT(vdev, fw_hdr, BOOT, 3, 17) ||
|
||||
(ivpu_test_mode & IVPU_TEST_MODE_D0I3_MSG_DISABLE))
|
||||
vdev->wa.disable_d0i3_msg = true;
|
||||
|
||||
/* Force enable the feature for testing purposes */
|
||||
if (ivpu_test_mode & IVPU_TEST_MODE_D0I3_MSG_ENABLE)
|
||||
vdev->wa.disable_d0i3_msg = false;
|
||||
|
||||
IVPU_PRINT_WA(disable_d0i3_msg);
|
||||
}
|
||||
|
||||
static int ivpu_fw_mem_init(struct ivpu_device *vdev)
|
||||
{
|
||||
|
|
@ -480,8 +464,6 @@ int ivpu_fw_init(struct ivpu_device *vdev)
|
|||
if (ret)
|
||||
goto err_fw_release;
|
||||
|
||||
ivpu_fw_init_wa(vdev);
|
||||
|
||||
ret = ivpu_fw_mem_init(vdev);
|
||||
if (ret)
|
||||
goto err_fw_release;
|
||||
|
|
@ -711,8 +693,7 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params
|
|||
if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW)
|
||||
boot_params->vpu_focus_present_timer_ms = IVPU_FOCUS_PRESENT_TIMER_MS;
|
||||
boot_params->dvfs_mode = vdev->fw->dvfs_mode;
|
||||
if (!IVPU_WA(disable_d0i3_msg))
|
||||
boot_params->d0i3_delayed_entry = 1;
|
||||
boot_params->d0i3_delayed_entry = 1;
|
||||
boot_params->d0i3_residency_time_us = 0;
|
||||
boot_params->d0i3_entry_vpu_ts = 0;
|
||||
if (IVPU_WA(disable_d0i2))
|
||||
|
|
|
|||
|
|
@ -97,7 +97,11 @@ ivpu_ipc_tx_prepare(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons,
|
|||
|
||||
memset(tx_buf, 0, sizeof(*tx_buf));
|
||||
tx_buf->ipc.data_addr = jsm_vpu_addr;
|
||||
/* TODO: Set data_size to actual JSM message size, not union of all messages */
|
||||
/*
|
||||
* Firmware expects full JSM message size regardless of the payload size.
|
||||
* Unused fields must be zeroed to allow future extensions of existing
|
||||
* commands without breaking compatibility.
|
||||
*/
|
||||
tx_buf->ipc.data_size = sizeof(*req);
|
||||
tx_buf->ipc.channel = cons->channel;
|
||||
tx_buf->ipc.src_node = 0;
|
||||
|
|
|
|||
|
|
@ -275,9 +275,6 @@ int ivpu_jsm_pwr_d0i3_enter(struct ivpu_device *vdev)
|
|||
struct vpu_jsm_msg resp;
|
||||
int ret;
|
||||
|
||||
if (IVPU_WA(disable_d0i3_msg))
|
||||
return 0;
|
||||
|
||||
req.payload.pwr_d0i3_enter.send_response = 1;
|
||||
|
||||
ret = ivpu_ipc_send_receive_internal(vdev, &req, VPU_JSM_MSG_PWR_D0I3_ENTER_DONE, &resp,
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
/**
|
||||
* API header changed (field names, documentation, formatting) but API itself has not been changed
|
||||
*/
|
||||
#define VPU_BOOT_API_VER_PATCH 4
|
||||
#define VPU_BOOT_API_VER_PATCH 5
|
||||
|
||||
/**
|
||||
* Index in the API version table
|
||||
|
|
@ -320,9 +320,11 @@ struct vpu_boot_params {
|
|||
u64 dvfs_param;
|
||||
/**
|
||||
* D0i3 delayed entry
|
||||
* Bit0: Disable CPU state save on D0i2 entry flow.
|
||||
* Bit 0: Disable CPU state save on D0i2 entry flow.
|
||||
* 0: Every D0i2 entry saves state. Save state IPC message ignored.
|
||||
* 1: IPC message required to save state on D0i3 entry flow.
|
||||
* NOTE: This parameter is deprecated starting NPU50xx+. Bit 0 is now hardcoded to 1,
|
||||
* meaning CPU state save always requires IPC message on D0i3 entry flow.
|
||||
*/
|
||||
u32 d0i3_delayed_entry;
|
||||
/** Time spent by VPU in D0i3 state */
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ bool __read_mostly mem_accounting;
|
|||
module_param(mem_accounting, bool, 0444);
|
||||
MODULE_PARM_DESC(mem_accounting,
|
||||
"Enable cgroup-based memory accounting for dma-buf heap allocations (default=false).");
|
||||
EXPORT_SYMBOL_NS_GPL(mem_accounting, "DMA_BUF_HEAP");
|
||||
|
||||
static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len,
|
||||
u32 fd_flags,
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
config DMABUF_HEAPS_SYSTEM
|
||||
bool "DMA-BUF System Heap"
|
||||
tristate "DMA-BUF System Heap"
|
||||
depends on DMABUF_HEAPS
|
||||
help
|
||||
Choose this option to enable the system dmabuf heap. The system heap
|
||||
is backed by pages from the buddy allocator. If in doubt, say Y.
|
||||
|
||||
config DMABUF_HEAPS_CMA
|
||||
bool "DMA-BUF CMA Heap"
|
||||
tristate "DMA-BUF CMA Heap"
|
||||
depends on DMABUF_HEAPS && DMA_CMA
|
||||
help
|
||||
Choose this option to enable dma-buf CMA heap. This heap is backed
|
||||
|
|
|
|||
|
|
@ -420,3 +420,6 @@ static int __init add_cma_heaps(void)
|
|||
}
|
||||
module_init(add_cma_heaps);
|
||||
MODULE_DESCRIPTION("DMA-BUF CMA Heap");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_IMPORT_NS("DMA_BUF");
|
||||
MODULE_IMPORT_NS("DMA_BUF_HEAP");
|
||||
|
|
|
|||
|
|
@ -537,3 +537,8 @@ static int __init system_heap_create(void)
|
|||
return 0;
|
||||
}
|
||||
module_init(system_heap_create);
|
||||
|
||||
MODULE_DESCRIPTION("DMA-BUF System Heap");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_IMPORT_NS("DMA_BUF");
|
||||
MODULE_IMPORT_NS("DMA_BUF_HEAP");
|
||||
|
|
|
|||
|
|
@ -2999,7 +2999,7 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence __rcu *
|
|||
/* Validate PDs, PTs and evicted DMABuf imports last. Otherwise BO
|
||||
* validations above would invalidate DMABuf imports again.
|
||||
*/
|
||||
ret = process_validate_vms(process_info, &exec.ticket);
|
||||
ret = process_validate_vms(process_info, drm_exec_ticket(&exec));
|
||||
if (ret) {
|
||||
pr_debug("Validating VMs failed, ret: %d\n", ret);
|
||||
goto validate_map_fail;
|
||||
|
|
@ -3040,7 +3040,7 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence __rcu *
|
|||
goto validate_map_fail;
|
||||
}
|
||||
|
||||
ret = amdgpu_vm_handle_moved(adev, peer_vm, &exec.ticket);
|
||||
ret = amdgpu_vm_handle_moved(adev, peer_vm, drm_exec_ticket(&exec));
|
||||
if (ret) {
|
||||
dev_dbg(adev->dev,
|
||||
"Memory eviction: handle moved failed, pid %8d. Try again.\n",
|
||||
|
|
|
|||
|
|
@ -850,7 +850,6 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
|
|||
struct amdgpu_vm *vm = &fpriv->vm;
|
||||
struct amdgpu_bo_list_entry *e;
|
||||
struct drm_gem_object *obj;
|
||||
unsigned long index;
|
||||
unsigned int i;
|
||||
int r;
|
||||
|
||||
|
|
@ -961,7 +960,7 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
|
|||
goto out_free_user_pages;
|
||||
}
|
||||
|
||||
drm_exec_for_each_locked_object(&p->exec, index, obj) {
|
||||
drm_exec_for_each_locked_object(&p->exec, obj) {
|
||||
r = amdgpu_cs_bo_validate(p, gem_to_amdgpu_bo(obj));
|
||||
if (unlikely(r))
|
||||
goto out_free_user_pages;
|
||||
|
|
@ -1158,7 +1157,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
|
|||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_vm_handle_moved(adev, vm, &p->exec.ticket);
|
||||
r = amdgpu_vm_handle_moved(adev, vm, drm_exec_ticket(&p->exec));
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
|
@ -1201,7 +1200,6 @@ static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p)
|
|||
struct drm_gpu_scheduler *sched;
|
||||
struct drm_gem_object *obj;
|
||||
struct dma_fence *fence;
|
||||
unsigned long index;
|
||||
unsigned int i;
|
||||
int r;
|
||||
|
||||
|
|
@ -1212,7 +1210,7 @@ static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p)
|
|||
return r;
|
||||
}
|
||||
|
||||
drm_exec_for_each_locked_object(&p->exec, index, obj) {
|
||||
drm_exec_for_each_locked_object(&p->exec, obj) {
|
||||
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
|
||||
|
||||
struct dma_resv *resv = bo->tbo.base.resv;
|
||||
|
|
@ -1281,7 +1279,6 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
|
|||
struct amdgpu_job *leader = p->gang_leader;
|
||||
struct amdgpu_bo_list_entry *e;
|
||||
struct drm_gem_object *gobj;
|
||||
unsigned long index;
|
||||
unsigned int i;
|
||||
uint64_t seq;
|
||||
int r;
|
||||
|
|
@ -1331,7 +1328,7 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
|
|||
}
|
||||
|
||||
p->fence = dma_fence_get(&leader->base.s_fence->finished);
|
||||
drm_exec_for_each_locked_object(&p->exec, index, gobj) {
|
||||
drm_exec_for_each_locked_object(&p->exec, gobj) {
|
||||
|
||||
ttm_bo_move_to_lru_tail_unlocked(&gem_to_amdgpu_bo(gobj)->tbo);
|
||||
|
||||
|
|
@ -1362,7 +1359,7 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
|
|||
cs->out.handle = seq;
|
||||
leader->uf_sequence = seq;
|
||||
|
||||
amdgpu_vm_bo_trace_cs(&fpriv->vm, &p->exec.ticket);
|
||||
amdgpu_vm_bo_trace_cs(&fpriv->vm, drm_exec_ticket(&p->exec));
|
||||
for (i = 0; i < p->gang_size; ++i) {
|
||||
amdgpu_job_free_resources(p->jobs[i]);
|
||||
trace_amdgpu_cs_ioctl(p->jobs[i]);
|
||||
|
|
@ -1797,7 +1794,7 @@ int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser,
|
|||
*map = mapping;
|
||||
|
||||
/* Double check that the BO is reserved by this CS */
|
||||
if (dma_resv_locking_ctx((*bo)->tbo.base.resv) != &parser->exec.ticket)
|
||||
if (dma_resv_locking_ctx((*bo)->tbo.base.resv) != drm_exec_ticket(&parser->exec))
|
||||
return -EINVAL;
|
||||
|
||||
/* Make sure VRAM is allocated contigiously */
|
||||
|
|
|
|||
|
|
@ -121,7 +121,6 @@ int amdgpu_evf_mgr_rearm(struct amdgpu_eviction_fence_mgr *evf_mgr,
|
|||
{
|
||||
struct amdgpu_eviction_fence *ev_fence;
|
||||
struct drm_gem_object *obj;
|
||||
unsigned long index;
|
||||
|
||||
/* Create and initialize a new eviction fence */
|
||||
ev_fence = kzalloc_obj(*ev_fence);
|
||||
|
|
@ -140,7 +139,7 @@ int amdgpu_evf_mgr_rearm(struct amdgpu_eviction_fence_mgr *evf_mgr,
|
|||
evf_mgr->ev_fence = &ev_fence->base;
|
||||
|
||||
/* And add it to all existing BOs */
|
||||
drm_exec_for_each_locked_object(exec, index, obj) {
|
||||
drm_exec_for_each_locked_object(exec, obj) {
|
||||
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
|
||||
|
||||
amdgpu_evf_mgr_attach_fence(evf_mgr, bo);
|
||||
|
|
|
|||
|
|
@ -205,6 +205,8 @@ config DRM_LONTIUM_LT8713SX
|
|||
config DRM_ITE_IT66121
|
||||
tristate "ITE IT66121 HDMI bridge"
|
||||
depends on OF
|
||||
select DRM_DISPLAY_HDMI_STATE_HELPER
|
||||
select DRM_DISPLAY_HELPER
|
||||
select DRM_KMS_HELPER
|
||||
select REGMAP_I2C
|
||||
help
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <drm/display/drm_hdmi_helper.h>
|
||||
#include <drm/display/drm_hdmi_state_helper.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_edid.h>
|
||||
|
|
@ -161,6 +163,14 @@
|
|||
#define IT66121_PKT_GEN_CTRL_ON BIT(0)
|
||||
#define IT66121_PKT_GEN_CTRL_RPT BIT(1)
|
||||
|
||||
#define IT66121_PKT_NULL_CTRL_REG 0xC9
|
||||
#define IT66121_PKT_NULL_CTRL_ON BIT(0)
|
||||
#define IT66121_PKT_NULL_CTRL_RPT BIT(1)
|
||||
|
||||
/* Null packet data registers (used for HDMI Vendor Specific InfoFrame) */
|
||||
#define IT66121_PKT_NULL_HB(n) (0x138 + (n))
|
||||
#define IT66121_PKT_NULL_PB(n) (0x13B + (n))
|
||||
|
||||
#define IT66121_AVIINFO_DB1_REG 0x158
|
||||
#define IT66121_AVIINFO_DB2_REG 0x159
|
||||
#define IT66121_AVIINFO_DB3_REG 0x15A
|
||||
|
|
@ -180,8 +190,16 @@
|
|||
#define IT66121_AVI_INFO_PKT_ON BIT(0)
|
||||
#define IT66121_AVI_INFO_PKT_RPT BIT(1)
|
||||
|
||||
#define IT66121_AUD_INFO_PKT_REG 0xCE
|
||||
#define IT66121_AUD_INFO_PKT_ON BIT(0)
|
||||
#define IT66121_AUD_INFO_PKT_RPT BIT(1)
|
||||
|
||||
#define IT66121_AUD_INFO_DB1_REG 0x168
|
||||
#define IT66121_AUD_INFO_CSUM_REG 0x16D
|
||||
|
||||
#define IT66121_HDMI_MODE_REG 0xC0
|
||||
#define IT66121_HDMI_MODE_HDMI BIT(0)
|
||||
#define IT66121_HDMI_MODE_DVI 0
|
||||
|
||||
#define IT66121_SYS_STATUS_REG 0x0E
|
||||
#define IT66121_SYS_STATUS_ACTIVE_IRQ BIT(7)
|
||||
|
|
@ -298,13 +316,11 @@ struct it66121_chip_info {
|
|||
struct it66121_ctx {
|
||||
struct regmap *regmap;
|
||||
struct drm_bridge bridge;
|
||||
struct drm_connector *connector;
|
||||
struct device *dev;
|
||||
struct gpio_desc *gpio_reset;
|
||||
struct i2c_client *client;
|
||||
u32 bus_width;
|
||||
struct mutex lock; /* Protects fields below and device registers */
|
||||
struct hdmi_avi_infoframe hdmi_avi_infoframe;
|
||||
struct {
|
||||
u8 ch_enable;
|
||||
u8 fs;
|
||||
|
|
@ -652,6 +668,60 @@ static int it66121_bridge_attach(struct drm_bridge *bridge,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void it66121_set_mode(struct it66121_ctx *ctx,
|
||||
struct drm_connector *connector,
|
||||
struct drm_atomic_commit *state)
|
||||
{
|
||||
const struct drm_connector_state *conn_state;
|
||||
const struct drm_crtc_state *crtc_state;
|
||||
const struct drm_display_mode *mode;
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
conn_state = drm_atomic_get_new_connector_state(state, connector);
|
||||
if (WARN_ON(!conn_state))
|
||||
return;
|
||||
|
||||
crtc = conn_state->crtc;
|
||||
if (WARN_ON(!crtc))
|
||||
return;
|
||||
|
||||
crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
|
||||
if (WARN_ON(!crtc_state))
|
||||
return;
|
||||
|
||||
mode = &crtc_state->adjusted_mode;
|
||||
|
||||
mutex_lock(&ctx->lock);
|
||||
|
||||
/* Set TX mode to HDMI or DVI */
|
||||
if (regmap_write(ctx->regmap, IT66121_HDMI_MODE_REG,
|
||||
connector->display_info.is_hdmi ?
|
||||
IT66121_HDMI_MODE_HDMI : IT66121_HDMI_MODE_DVI))
|
||||
goto unlock;
|
||||
|
||||
if ((ctx->id == ID_IT66121 || ctx->id == ID_IT66122) &&
|
||||
regmap_write_bits(ctx->regmap, IT66121_CLK_BANK_REG,
|
||||
IT66121_CLK_BANK_PWROFF_TXCLK,
|
||||
IT66121_CLK_BANK_PWROFF_TXCLK)) {
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (it66121_configure_input(ctx))
|
||||
goto unlock;
|
||||
|
||||
if (it66121_configure_afe(ctx, mode))
|
||||
goto unlock;
|
||||
|
||||
if ((ctx->id == ID_IT66121 || ctx->id == ID_IT66122) &&
|
||||
regmap_write_bits(ctx->regmap, IT66121_CLK_BANK_REG,
|
||||
IT66121_CLK_BANK_PWROFF_TXCLK, 0)) {
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&ctx->lock);
|
||||
}
|
||||
|
||||
static int it66121_set_mute(struct it66121_ctx *ctx, bool mute)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -724,9 +794,15 @@ static void it66121_bridge_enable(struct drm_bridge *bridge,
|
|||
struct drm_atomic_commit *state)
|
||||
{
|
||||
struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge);
|
||||
struct drm_connector *connector;
|
||||
|
||||
ctx->connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
|
||||
connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
|
||||
if (WARN_ON(!connector))
|
||||
return;
|
||||
|
||||
drm_atomic_helper_connector_hdmi_update_infoframes(connector, state);
|
||||
|
||||
it66121_set_mode(ctx, connector, state);
|
||||
it66121_set_mute(ctx, false);
|
||||
}
|
||||
|
||||
|
|
@ -736,8 +812,6 @@ static void it66121_bridge_disable(struct drm_bridge *bridge,
|
|||
struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge);
|
||||
|
||||
it66121_set_mute(ctx, true);
|
||||
|
||||
ctx->connector = NULL;
|
||||
}
|
||||
|
||||
static int it66121_bridge_check(struct drm_bridge *bridge,
|
||||
|
|
@ -758,90 +832,6 @@ static int it66121_bridge_check(struct drm_bridge *bridge,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
void it66121_bridge_mode_set(struct drm_bridge *bridge,
|
||||
const struct drm_display_mode *mode,
|
||||
const struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
u8 buf[HDMI_INFOFRAME_SIZE(AVI)];
|
||||
struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ctx->lock);
|
||||
|
||||
ret = drm_hdmi_avi_infoframe_from_display_mode(&ctx->hdmi_avi_infoframe, ctx->connector,
|
||||
adjusted_mode);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to setup AVI infoframe: %d\n", ret);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = hdmi_avi_infoframe_pack(&ctx->hdmi_avi_infoframe, buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("Failed to pack infoframe: %d\n", ret);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/* Write new AVI infoframe packet */
|
||||
ret = regmap_bulk_write(ctx->regmap, IT66121_AVIINFO_DB1_REG,
|
||||
&buf[HDMI_INFOFRAME_HEADER_SIZE],
|
||||
HDMI_AVI_INFOFRAME_SIZE);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
if (regmap_write(ctx->regmap, IT66121_AVIINFO_CSUM_REG, buf[3]))
|
||||
goto unlock;
|
||||
|
||||
/* Enable AVI infoframe */
|
||||
if (regmap_write(ctx->regmap, IT66121_AVI_INFO_PKT_REG,
|
||||
IT66121_AVI_INFO_PKT_ON | IT66121_AVI_INFO_PKT_RPT))
|
||||
goto unlock;
|
||||
|
||||
/* Set TX mode to HDMI */
|
||||
if (regmap_write(ctx->regmap, IT66121_HDMI_MODE_REG, IT66121_HDMI_MODE_HDMI))
|
||||
goto unlock;
|
||||
|
||||
if ((ctx->id == ID_IT66121 || ctx->id == ID_IT66122) &&
|
||||
regmap_write_bits(ctx->regmap, IT66121_CLK_BANK_REG,
|
||||
IT66121_CLK_BANK_PWROFF_TXCLK,
|
||||
IT66121_CLK_BANK_PWROFF_TXCLK)) {
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (it66121_configure_input(ctx))
|
||||
goto unlock;
|
||||
|
||||
if (it66121_configure_afe(ctx, adjusted_mode))
|
||||
goto unlock;
|
||||
|
||||
if ((ctx->id == ID_IT66121 || ctx->id == ID_IT66122) &&
|
||||
regmap_write_bits(ctx->regmap, IT66121_CLK_BANK_REG,
|
||||
IT66121_CLK_BANK_PWROFF_TXCLK, 0)) {
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&ctx->lock);
|
||||
}
|
||||
|
||||
static enum drm_mode_status it66121_bridge_mode_valid(struct drm_bridge *bridge,
|
||||
const struct drm_display_info *info,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge);
|
||||
unsigned long max_clock;
|
||||
|
||||
max_clock = (ctx->bus_width == 12) ? 74250 : 148500;
|
||||
|
||||
if (mode->clock > max_clock)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
if (mode->clock < 25000)
|
||||
return MODE_CLOCK_LOW;
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
it66121_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connector)
|
||||
{
|
||||
|
|
@ -872,6 +862,128 @@ static void it66121_bridge_hpd_disable(struct drm_bridge *bridge)
|
|||
dev_err(ctx->dev, "failed to disable HPD IRQ\n");
|
||||
}
|
||||
|
||||
static enum drm_mode_status
|
||||
it66121_bridge_hdmi_tmds_char_rate_valid(const struct drm_bridge *bridge,
|
||||
const struct drm_display_mode *mode,
|
||||
unsigned long long tmds_rate)
|
||||
{
|
||||
const struct it66121_ctx *ctx =
|
||||
container_of(bridge, const struct it66121_ctx, bridge);
|
||||
unsigned long long max_rate;
|
||||
|
||||
max_rate = (ctx->bus_width == 12) ? 74250000ULL : 148500000ULL;
|
||||
|
||||
if (tmds_rate > max_rate)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
if (tmds_rate < HDMI_TMDS_CHAR_RATE_MIN_HZ)
|
||||
return MODE_CLOCK_LOW;
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static int it66121_bridge_hdmi_clear_avi_infoframe(struct drm_bridge *bridge)
|
||||
{
|
||||
struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge);
|
||||
|
||||
/* Clear both IT66121_AVI_INFO_PKT_ON and IT66121_AVI_INFO_PKT_RPT */
|
||||
return regmap_write(ctx->regmap, IT66121_AVI_INFO_PKT_REG, 0);
|
||||
}
|
||||
|
||||
static int it66121_bridge_hdmi_write_avi_infoframe(struct drm_bridge *bridge,
|
||||
const u8 *buffer, size_t len)
|
||||
{
|
||||
struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ctx->lock);
|
||||
|
||||
/* Write new AVI infoframe packet */
|
||||
ret = regmap_bulk_write(ctx->regmap, IT66121_AVIINFO_DB1_REG,
|
||||
&buffer[HDMI_INFOFRAME_HEADER_SIZE],
|
||||
HDMI_AVI_INFOFRAME_SIZE);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
ret = regmap_write(ctx->regmap, IT66121_AVIINFO_CSUM_REG, buffer[3]);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
/* Enable AVI infoframe */
|
||||
ret = regmap_write(ctx->regmap, IT66121_AVI_INFO_PKT_REG,
|
||||
IT66121_AVI_INFO_PKT_ON | IT66121_AVI_INFO_PKT_RPT);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&ctx->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int it66121_bridge_hdmi_clear_hdmi_infoframe(struct drm_bridge *bridge)
|
||||
{
|
||||
struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge);
|
||||
|
||||
/* Clear both IT66121_PKT_NULL_CTRL_ON and IT66121_PKT_NULL_CTRL_RPT */
|
||||
return regmap_write(ctx->regmap, IT66121_PKT_NULL_CTRL_REG, 0);
|
||||
}
|
||||
|
||||
static int it66121_bridge_hdmi_write_hdmi_infoframe(struct drm_bridge *bridge,
|
||||
const u8 *buffer, size_t len)
|
||||
{
|
||||
struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ctx->lock);
|
||||
|
||||
/* Write new HDMI Vendor Specific Infoframe packet */
|
||||
ret = regmap_bulk_write(ctx->regmap, IT66121_PKT_NULL_HB(0), buffer, len);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
/* Enable HDMI Vendor Specific Infoframe */
|
||||
ret = regmap_write(ctx->regmap, IT66121_PKT_NULL_CTRL_REG,
|
||||
IT66121_PKT_NULL_CTRL_ON | IT66121_PKT_NULL_CTRL_RPT);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&ctx->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int it66121_bridge_hdmi_clear_audio_infoframe(struct drm_bridge *bridge)
|
||||
{
|
||||
struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge);
|
||||
|
||||
/* Clear both IT66121_AUD_INFO_PKT_ON and IT66121_AUD_INFO_PKT_RPT */
|
||||
return regmap_write(ctx->regmap, IT66121_AUD_INFO_PKT_REG, 0);
|
||||
}
|
||||
|
||||
static int it66121_bridge_hdmi_write_audio_infoframe(struct drm_bridge *bridge,
|
||||
const u8 *buffer, size_t len)
|
||||
{
|
||||
struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ctx->lock);
|
||||
|
||||
/* Write new Audio infoframe packet */
|
||||
ret = regmap_bulk_write(ctx->regmap, IT66121_AUD_INFO_DB1_REG,
|
||||
&buffer[HDMI_INFOFRAME_HEADER_SIZE],
|
||||
min_t(size_t, len - HDMI_INFOFRAME_HEADER_SIZE, 5));
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
ret = regmap_write(ctx->regmap, IT66121_AUD_INFO_CSUM_REG, buffer[3]);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
/* Enable Audio infoframe */
|
||||
ret = regmap_write(ctx->regmap, IT66121_AUD_INFO_PKT_REG,
|
||||
IT66121_AUD_INFO_PKT_ON | IT66121_AUD_INFO_PKT_RPT);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&ctx->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct drm_edid *it66121_bridge_edid_read(struct drm_bridge *bridge,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
|
|
@ -1359,6 +1471,10 @@ static int it66121_hdmi_audio_prepare(struct drm_bridge *bridge,
|
|||
out:
|
||||
mutex_unlock(&ctx->lock);
|
||||
|
||||
if (!ret)
|
||||
ret = drm_atomic_helper_connector_hdmi_update_audio_infoframe(connector,
|
||||
¶ms->cea);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1384,6 +1500,8 @@ static void it66121_hdmi_audio_shutdown(struct drm_bridge *bridge,
|
|||
int ret;
|
||||
struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge);
|
||||
|
||||
drm_atomic_helper_connector_hdmi_clear_audio_infoframe(connector);
|
||||
|
||||
mutex_lock(&ctx->lock);
|
||||
ret = it661221_audio_output_enable(ctx, false);
|
||||
if (ret)
|
||||
|
|
@ -1432,12 +1550,17 @@ static const struct drm_bridge_funcs it66121_bridge_funcs = {
|
|||
.atomic_enable = it66121_bridge_enable,
|
||||
.atomic_disable = it66121_bridge_disable,
|
||||
.atomic_check = it66121_bridge_check,
|
||||
.mode_set = it66121_bridge_mode_set,
|
||||
.mode_valid = it66121_bridge_mode_valid,
|
||||
.detect = it66121_bridge_detect,
|
||||
.edid_read = it66121_bridge_edid_read,
|
||||
.hpd_enable = it66121_bridge_hpd_enable,
|
||||
.hpd_disable = it66121_bridge_hpd_disable,
|
||||
.hdmi_tmds_char_rate_valid = it66121_bridge_hdmi_tmds_char_rate_valid,
|
||||
.hdmi_clear_avi_infoframe = it66121_bridge_hdmi_clear_avi_infoframe,
|
||||
.hdmi_write_avi_infoframe = it66121_bridge_hdmi_write_avi_infoframe,
|
||||
.hdmi_clear_hdmi_infoframe = it66121_bridge_hdmi_clear_hdmi_infoframe,
|
||||
.hdmi_write_hdmi_infoframe = it66121_bridge_hdmi_write_hdmi_infoframe,
|
||||
.hdmi_clear_audio_infoframe = it66121_bridge_hdmi_clear_audio_infoframe,
|
||||
.hdmi_write_audio_infoframe = it66121_bridge_hdmi_write_audio_infoframe,
|
||||
.hdmi_audio_startup = it66121_hdmi_audio_startup,
|
||||
.hdmi_audio_prepare = it66121_hdmi_audio_prepare,
|
||||
.hdmi_audio_shutdown = it66121_hdmi_audio_shutdown,
|
||||
|
|
@ -1543,7 +1666,10 @@ static int it66121_probe(struct i2c_client *client)
|
|||
|
||||
ctx->bridge.of_node = dev->of_node;
|
||||
ctx->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
|
||||
ctx->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID;
|
||||
ctx->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID |
|
||||
DRM_BRIDGE_OP_HDMI;
|
||||
ctx->bridge.vendor = "ITE";
|
||||
ctx->bridge.product = "IT66121";
|
||||
if (client->irq > 0) {
|
||||
ctx->bridge.ops |= DRM_BRIDGE_OP_HPD;
|
||||
|
||||
|
|
|
|||
|
|
@ -2546,6 +2546,8 @@ static const struct dpcd_quirk dpcd_quirk_list[] = {
|
|||
{ OUI(0x00, 0x00, 0x00), DEVICE_ID('C', 'H', '7', '5', '1', '1'), false, BIT(DP_DPCD_QUIRK_NO_SINK_COUNT) },
|
||||
/* Synaptics DP1.4 MST hubs can support DSC without virtual DPCD */
|
||||
{ OUI(0x90, 0xCC, 0x24), DEVICE_ID_ANY, true, BIT(DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD) },
|
||||
/* Realtek DP1.4 MST hubs can support DSC without virtual DPCD */
|
||||
{ OUI(0x00, 0xe0, 0x4c), DEVICE_ID('D', 'p', '1', '.', '4', 0), true, BIT(DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD) },
|
||||
/* Synaptics DP1.4 MST hubs require DSC for some modes on which it applies HBLANK expansion. */
|
||||
{ OUI(0x90, 0xCC, 0x24), DEVICE_ID_ANY, true, BIT(DP_DPCD_QUIRK_HBLANK_EXPANSION_REQUIRES_DSC) },
|
||||
/* MediaTek panels (at least in U3224KBA) require DSC for modes with a short HBLANK on UHBR links. */
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
*
|
||||
* struct drm_gem_object *obj;
|
||||
* struct drm_exec exec;
|
||||
* unsigned long index;
|
||||
* int ret;
|
||||
*
|
||||
* drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT);
|
||||
|
|
@ -40,7 +39,7 @@
|
|||
* goto error;
|
||||
* }
|
||||
*
|
||||
* drm_exec_for_each_locked_object(&exec, index, obj) {
|
||||
* drm_exec_for_each_locked_object(&exec, obj) {
|
||||
* dma_resv_add_fence(obj->resv, fence, DMA_RESV_USAGE_READ);
|
||||
* ...
|
||||
* }
|
||||
|
|
@ -49,16 +48,12 @@
|
|||
* See struct dma_exec for more details.
|
||||
*/
|
||||
|
||||
/* Dummy value used to initially enter the retry loop */
|
||||
#define DRM_EXEC_DUMMY ((void *)~0)
|
||||
|
||||
/* Unlock all objects and drop references */
|
||||
static void drm_exec_unlock_all(struct drm_exec *exec)
|
||||
{
|
||||
struct drm_gem_object *obj;
|
||||
unsigned long index;
|
||||
|
||||
drm_exec_for_each_locked_object_reverse(exec, index, obj) {
|
||||
drm_exec_for_each_locked_object_reverse(exec, obj) {
|
||||
dma_resv_unlock(obj->resv);
|
||||
drm_gem_object_put(obj);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1553,9 +1553,8 @@ drm_gpuvm_resv_add_fence(struct drm_gpuvm *gpuvm,
|
|||
enum dma_resv_usage extobj_usage)
|
||||
{
|
||||
struct drm_gem_object *obj;
|
||||
unsigned long index;
|
||||
|
||||
drm_exec_for_each_locked_object(exec, index, obj) {
|
||||
drm_exec_for_each_locked_object(exec, obj) {
|
||||
dma_resv_assert_held(obj->resv);
|
||||
dma_resv_add_fence(obj->resv, fence,
|
||||
drm_gpuvm_is_extobj(gpuvm, obj) ?
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ static void drm_panel_add_release(void *data)
|
|||
|
||||
/**
|
||||
* devm_drm_panel_add - add a panel to the global registry using devres
|
||||
* @dev: device to which the panel is attached
|
||||
* @panel: panel to add
|
||||
*
|
||||
* Add a panel to the global registry so that it can be looked
|
||||
|
|
|
|||
|
|
@ -293,7 +293,7 @@ nvkm_gsp_rpc_rd(struct nvkm_gsp *gsp, u32 fn, u32 argc)
|
|||
{
|
||||
void *argv = nvkm_gsp_rpc_get(gsp, fn, argc);
|
||||
|
||||
if (IS_ERR_OR_NULL(argv))
|
||||
if (IS_ERR(argv))
|
||||
return argv;
|
||||
|
||||
return nvkm_gsp_rpc_push(gsp, argv, NVKM_GSP_RPC_REPLY_RECV, argc);
|
||||
|
|
@ -373,7 +373,7 @@ nvkm_gsp_rm_alloc_get(struct nvkm_gsp_object *parent, u32 handle, u32 oclass, u3
|
|||
object->handle = handle;
|
||||
|
||||
argv = gsp->rm->api->alloc->get(object, oclass, argc);
|
||||
if (IS_ERR_OR_NULL(argv)) {
|
||||
if (IS_ERR(argv)) {
|
||||
object->client = NULL;
|
||||
return argv;
|
||||
}
|
||||
|
|
@ -415,8 +415,8 @@ nvkm_gsp_rm_alloc(struct nvkm_gsp_object *parent, u32 handle, u32 oclass, u32 ar
|
|||
{
|
||||
void *argv = nvkm_gsp_rm_alloc_get(parent, handle, oclass, argc, object);
|
||||
|
||||
if (IS_ERR_OR_NULL(argv))
|
||||
return argv ? PTR_ERR(argv) : -EIO;
|
||||
if (IS_ERR(argv))
|
||||
return PTR_ERR(argv);
|
||||
|
||||
return nvkm_gsp_rm_alloc_wr(object, argv);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2530,6 +2530,7 @@ nv170_chipset = {
|
|||
.vfn = { 0x00000001, ga100_vfn_new },
|
||||
.ce = { 0x000003ff, ga100_ce_new },
|
||||
.fifo = { 0x00000001, ga100_fifo_new },
|
||||
.sec2 = { 0x00000001, tu102_sec2_new },
|
||||
};
|
||||
|
||||
static const struct nvkm_device_chip
|
||||
|
|
@ -3341,6 +3342,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
|
|||
case 0x166: device->chip = &nv166_chipset; break;
|
||||
case 0x167: device->chip = &nv167_chipset; break;
|
||||
case 0x168: device->chip = &nv168_chipset; break;
|
||||
case 0x170: device->chip = &nv170_chipset; break;
|
||||
case 0x172: device->chip = &nv172_chipset; break;
|
||||
case 0x173: device->chip = &nv173_chipset; break;
|
||||
case 0x174: device->chip = &nv174_chipset; break;
|
||||
|
|
@ -3360,14 +3362,6 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
|
|||
case 0x1b6: device->chip = &nv1b6_chipset; break;
|
||||
case 0x1b7: device->chip = &nv1b7_chipset; break;
|
||||
default:
|
||||
if (nvkm_boolopt(device->cfgopt, "NvEnableUnsupportedChipsets", false)) {
|
||||
switch (device->chipset) {
|
||||
case 0x170: device->chip = &nv170_chipset; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!device->chip) {
|
||||
nvdev_error(device, "unknown chipset (%08x)\n", boot0);
|
||||
ret = -ENODEV;
|
||||
|
|
|
|||
|
|
@ -65,13 +65,14 @@ pramin_init(struct nvkm_bios *bios, const char *name)
|
|||
|
||||
/* we can't get the bios image pointer without PDISP */
|
||||
if (device->card_type >= GA100)
|
||||
addr = device->chipset == 0x170; /*XXX: find the fuse reg for this */
|
||||
addr = nvkm_rd32(device, 0x820c04);
|
||||
else
|
||||
if (device->card_type >= GM100)
|
||||
addr = nvkm_rd32(device, 0x021c04);
|
||||
else
|
||||
if (device->card_type >= NV_C0)
|
||||
addr = nvkm_rd32(device, 0x022500);
|
||||
|
||||
if (addr & 0x00000001) {
|
||||
nvkm_debug(subdev, "... display disabled\n");
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
|
|
|||
|
|
@ -24,34 +24,126 @@
|
|||
|
||||
#include <subdev/pci.h>
|
||||
|
||||
#define NV_PBUS_IFR_FMT_FIXED0_SIGNATURE_VALUE 0x4947564E /* "NVGI" */
|
||||
#define NV_ROM_DIRECTORY_IDENTIFIER 0x44524652 /* "RFRD" */
|
||||
|
||||
struct priv {
|
||||
struct nvkm_device *device;
|
||||
u32 pci_rom_offset;
|
||||
};
|
||||
|
||||
static u32
|
||||
nvbios_prom_read(void *data, u32 offset, u32 length, struct nvkm_bios *bios)
|
||||
{
|
||||
struct nvkm_device *device = data;
|
||||
struct priv *priv = data;
|
||||
struct nvkm_device *device = priv->device;
|
||||
u32 i;
|
||||
if (offset + length <= 0x00100000) {
|
||||
for (i = offset; i < offset + length; i += 4)
|
||||
*(u32 *)&bios->data[i] = nvkm_rd32(device, 0x300000 + i);
|
||||
return length;
|
||||
}
|
||||
return 0;
|
||||
|
||||
/* Make sure we don't try to read past the end of data[] */
|
||||
if (offset + length > bios->size)
|
||||
return 0;
|
||||
|
||||
/* Make sure the read falls within the 1MB PROM window */
|
||||
if (offset + priv->pci_rom_offset + length > 0x00100000)
|
||||
return 0;
|
||||
|
||||
for (i = offset; i < offset + length; i += 4)
|
||||
*(u32 *)&bios->data[i] = nvkm_rd32(device, 0x300000 + priv->pci_rom_offset + i);
|
||||
return length;
|
||||
}
|
||||
|
||||
static void
|
||||
nvbios_prom_fini(void *data)
|
||||
{
|
||||
struct nvkm_device *device = data;
|
||||
struct priv *priv = data;
|
||||
struct nvkm_device *device = priv->device;
|
||||
|
||||
nvkm_pci_rom_shadow(device->pci, true);
|
||||
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
static void *
|
||||
nvbios_prom_init(struct nvkm_bios *bios, const char *name)
|
||||
{
|
||||
struct nvkm_device *device = bios->subdev.device;
|
||||
struct priv *priv;
|
||||
u32 fixed0;
|
||||
|
||||
/* There is no PROM on NV4x iGPUs */
|
||||
if (device->card_type == NV_40 && device->chipset >= 0x4c)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
priv = kzalloc_obj(*priv);
|
||||
if (!priv)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
/* Disable the PCI ROM shadow so that we can read PROM. */
|
||||
nvkm_pci_rom_shadow(device->pci, false);
|
||||
return device;
|
||||
|
||||
/*
|
||||
* Check for an IFR header. If present, parse it to find the actual PCI ROM header.
|
||||
*
|
||||
* The IFR header is documented in Documentation/gpu/nova/core/vbios.rst
|
||||
*/
|
||||
fixed0 = nvkm_rd32(device, 0x300000);
|
||||
if (fixed0 == NV_PBUS_IFR_FMT_FIXED0_SIGNATURE_VALUE) {
|
||||
u32 fixed1 = nvkm_rd32(device, 0x300004);
|
||||
u8 version = (fixed1 >> 8) & 0xff;
|
||||
u32 fixed2, data_size, offset, signature;
|
||||
|
||||
switch (version) {
|
||||
case 1:
|
||||
case 2:
|
||||
data_size = (fixed1 >> 16) & 0x7fff;
|
||||
priv->pci_rom_offset = nvkm_rd32(device, 0x300000 + data_size + 4);
|
||||
break;
|
||||
case 3:
|
||||
fixed2 = nvkm_rd32(device, 0x300008);
|
||||
data_size = fixed2 & 0x000fffff;
|
||||
|
||||
/* ROM directory offset */
|
||||
offset = nvkm_rd32(device, 0x300000 + data_size) + 4096;
|
||||
|
||||
signature = nvkm_rd32(device, 0x300000 + offset);
|
||||
if (signature != NV_ROM_DIRECTORY_IDENTIFIER) {
|
||||
nvkm_error(&bios->subdev, "could not find IFR ROM directory\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
priv->pci_rom_offset = nvkm_rd32(device, 0x300000 + offset + 8);
|
||||
|
||||
break;
|
||||
default:
|
||||
nvkm_error(&bios->subdev, "unsupported IFR header version %u\n",
|
||||
version);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Double-check that the offset is valid */
|
||||
if (priv->pci_rom_offset >= 0x00100000) {
|
||||
nvkm_error(&bios->subdev,
|
||||
"PCI ROM offset of 0x%x is too large\n", priv->pci_rom_offset);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* If there is an IFR header, there must also be a PCI ROM header. */
|
||||
signature = nvkm_rd32(device, 0x300000 + priv->pci_rom_offset) & 0xffff;
|
||||
if (signature != 0xaa55) {
|
||||
nvkm_error(&bios->subdev,
|
||||
"could not find PCI ROM signature at offset 0x%x\n",
|
||||
priv->pci_rom_offset);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
priv->device = device;
|
||||
return priv;
|
||||
|
||||
fail:
|
||||
nvkm_pci_rom_shadow(device->pci, true);
|
||||
kfree(priv);
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
const struct nvbios_source
|
||||
|
|
|
|||
|
|
@ -63,7 +63,6 @@ static struct nvkm_gsp_fwif
|
|||
ga100_gsps[] = {
|
||||
{ 1, tu102_gsp_load, &ga100_gsp, &r570_rm_tu102, "570.144" },
|
||||
{ 0, tu102_gsp_load, &ga100_gsp, &r535_rm_tu102, "535.113.01" },
|
||||
{ -1, gv100_gsp_nofw, &gv100_gsp },
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ r535_gsp_rpc_rm_free(struct nvkm_gsp_object *object)
|
|||
client->object.handle, object->handle);
|
||||
|
||||
rpc = nvkm_gsp_rpc_get(gsp, NV_VGPU_MSG_FUNCTION_FREE, sizeof(*rpc));
|
||||
if (WARN_ON(IS_ERR_OR_NULL(rpc)))
|
||||
if (WARN_ON(IS_ERR(rpc)))
|
||||
return -EIO;
|
||||
|
||||
rpc->params.hRoot = client->object.handle;
|
||||
|
|
@ -60,7 +60,7 @@ r535_gsp_rpc_rm_alloc_push(struct nvkm_gsp_object *object, void *params)
|
|||
void *ret = NULL;
|
||||
|
||||
rpc = nvkm_gsp_rpc_push(gsp, rpc, NVKM_GSP_RPC_REPLY_RECV, sizeof(*rpc));
|
||||
if (IS_ERR_OR_NULL(rpc))
|
||||
if (IS_ERR(rpc))
|
||||
return rpc;
|
||||
|
||||
if (rpc->status) {
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ r535_bar_bar2_update_pde(struct nvkm_gsp *gsp, u8 page_shift, u64 pdbe)
|
|||
rpc_update_bar_pde_v15_00 *rpc;
|
||||
|
||||
rpc = nvkm_gsp_rpc_get(gsp, NV_VGPU_MSG_FUNCTION_UPDATE_BAR_PDE, sizeof(*rpc));
|
||||
if (WARN_ON(IS_ERR_OR_NULL(rpc)))
|
||||
if (WARN_ON(IS_ERR(rpc)))
|
||||
return -EIO;
|
||||
|
||||
rpc->info.barType = NV_RPC_UPDATE_PDE_BAR_2;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ r535_gsp_rpc_rm_ctrl_push(struct nvkm_gsp_object *object, void **params, u32 rep
|
|||
int ret = 0;
|
||||
|
||||
rpc = nvkm_gsp_rpc_push(gsp, rpc, NVKM_GSP_RPC_REPLY_RECV, repc);
|
||||
if (IS_ERR_OR_NULL(rpc)) {
|
||||
if (IS_ERR(rpc)) {
|
||||
*params = NULL;
|
||||
return PTR_ERR(rpc);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -324,7 +324,7 @@ r535_gsp_msgq_recv(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *retries)
|
|||
u32 size;
|
||||
|
||||
rpc = r535_gsp_msgq_peek(gsp, sizeof(*rpc), info.retries);
|
||||
if (IS_ERR_OR_NULL(rpc)) {
|
||||
if (IS_ERR(rpc)) {
|
||||
kvfree(buf);
|
||||
return rpc;
|
||||
}
|
||||
|
|
@ -333,7 +333,7 @@ r535_gsp_msgq_recv(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *retries)
|
|||
info.continuation = true;
|
||||
|
||||
rpc = r535_gsp_msgq_recv_one_elem(gsp, &info);
|
||||
if (IS_ERR_OR_NULL(rpc)) {
|
||||
if (IS_ERR(rpc)) {
|
||||
kvfree(buf);
|
||||
return rpc;
|
||||
}
|
||||
|
|
@ -459,11 +459,11 @@ r535_gsp_msg_recv(struct nvkm_gsp *gsp, int fn, u32 gsp_rpc_len)
|
|||
|
||||
retry:
|
||||
rpc = r535_gsp_msgq_peek(gsp, sizeof(*rpc), &retries);
|
||||
if (IS_ERR_OR_NULL(rpc))
|
||||
if (IS_ERR(rpc))
|
||||
return rpc;
|
||||
|
||||
rpc = r535_gsp_msgq_recv(gsp, gsp_rpc_len, &retries);
|
||||
if (IS_ERR_OR_NULL(rpc))
|
||||
if (IS_ERR(rpc))
|
||||
return rpc;
|
||||
|
||||
if (rpc->rpc_result) {
|
||||
|
|
@ -561,7 +561,7 @@ r535_gsp_rpc_handle_reply(struct nvkm_gsp *gsp, u32 fn,
|
|||
break;
|
||||
case NVKM_GSP_RPC_REPLY_RECV:
|
||||
reply = r535_gsp_msg_recv(gsp, fn, gsp_rpc_len);
|
||||
if (!IS_ERR_OR_NULL(reply))
|
||||
if (!IS_ERR(reply))
|
||||
repv = reply->data;
|
||||
else
|
||||
repv = reply;
|
||||
|
|
|
|||
|
|
@ -246,7 +246,7 @@ tu102_gsp_wpr_meta_init(struct nvkm_gsp *gsp)
|
|||
meta->bootBinOffset = gsp->fb.wpr2.boot.addr;
|
||||
meta->frtsOffset = gsp->fb.wpr2.frts.addr;
|
||||
meta->frtsSize = gsp->fb.wpr2.frts.size;
|
||||
meta->gspFwWprEnd = ALIGN_DOWN(gsp->fb.bios.vga_workspace.addr, 0x20000);
|
||||
meta->gspFwWprEnd = ALIGN_DOWN(gsp->fb.bios.addr, 0x20000);
|
||||
meta->fbSize = gsp->fb.size;
|
||||
meta->vgaWorkspaceOffset = gsp->fb.bios.vga_workspace.addr;
|
||||
meta->vgaWorkspaceSize = gsp->fb.bios.vga_workspace.size;
|
||||
|
|
@ -291,6 +291,42 @@ tu102_gsp_vga_workspace_addr(struct nvkm_gsp *gsp, u64 fb_size)
|
|||
return addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the MMU_LOCK range programmed by VBIOS.
|
||||
*
|
||||
* The row remapper reserves a small amount of DRAM at the end of FB for
|
||||
* spare rows used to repair memory errors. The register used to report
|
||||
* FB size rounds to 1GB boundaries, and VBIOS rounds up rather than
|
||||
* down -- reporting a larger size than is actually usable. To
|
||||
* compensate, VBIOS programs MMU_LOCK to fence off the unusable region
|
||||
* at the top. We must read this and keep WPR below it.
|
||||
*
|
||||
* Returns the low address of the locked region, or 0 if not set.
|
||||
*/
|
||||
static u64
|
||||
ga100_gsp_mmu_lock_lo(struct nvkm_gsp *gsp)
|
||||
{
|
||||
struct nvkm_device *device = gsp->subdev.device;
|
||||
u32 lo, hi;
|
||||
u64 addr_lo, addr_hi;
|
||||
|
||||
/* NV_PFB_PRI_MMU_LOCK_CFG_PRIV_LEVEL_MASK */
|
||||
if (!(nvkm_rd32(device, 0x1fa7c8) & 0x00000001))
|
||||
return 0;
|
||||
|
||||
lo = nvkm_rd32(device, 0x1fa82c); /* NV_PFB_PRI_MMU_LOCK_ADDR_LO */
|
||||
hi = nvkm_rd32(device, 0x1fa830); /* NV_PFB_PRI_MMU_LOCK_ADDR_HI */
|
||||
|
||||
addr_lo = (u64)(lo >> 4) << 12;
|
||||
addr_hi = (u64)(hi >> 4) << 12;
|
||||
|
||||
if (addr_hi < addr_lo)
|
||||
return 0;
|
||||
|
||||
nvkm_debug(&gsp->subdev, "MMU_LOCK range: 0x%llx - 0x%llx\n", addr_lo, addr_hi);
|
||||
return addr_lo;
|
||||
}
|
||||
|
||||
int
|
||||
tu102_gsp_oneinit(struct nvkm_gsp *gsp)
|
||||
{
|
||||
|
|
@ -304,6 +340,19 @@ tu102_gsp_oneinit(struct nvkm_gsp *gsp)
|
|||
gsp->fb.bios.addr = gsp->fb.bios.vga_workspace.addr;
|
||||
gsp->fb.bios.size = gsp->fb.bios.vga_workspace.size;
|
||||
|
||||
/*
|
||||
* On GA100, VBIOS may lock the top of FB via MMU_LOCK to reserve
|
||||
* space for the row remapper. Mirror OpenRM's kgspCalculateFbLayout
|
||||
* by clamping bios.addr to min(mmuLockLo, vgaWorkspace) so that the
|
||||
* entire WPR2 layout and gspFwWprEnd stay within usable FB.
|
||||
*/
|
||||
if (device->chipset == 0x170) {
|
||||
u64 lock_lo = ga100_gsp_mmu_lock_lo(gsp);
|
||||
|
||||
if (lock_lo)
|
||||
gsp->fb.bios.addr = min(gsp->fb.bios.addr, lock_lo);
|
||||
}
|
||||
|
||||
ret = gsp->func->booter.ctor(gsp, "booter-load", gsp->fws.booter.load,
|
||||
&device->sec2->falcon, &gsp->booter.load);
|
||||
if (ret)
|
||||
|
|
@ -318,8 +367,13 @@ tu102_gsp_oneinit(struct nvkm_gsp *gsp)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Calculate FB layout. */
|
||||
gsp->fb.wpr2.frts.size = 0x100000;
|
||||
/*
|
||||
* Calculate FB layout. FRTS is a memory region created by running the FWSEC-FRTS
|
||||
* command, which writes power management data into WPR2. On GA100, the booter
|
||||
* firmware handles WPR2 setup directly and FRTS data is not needed, so no FRTS
|
||||
* region is reserved.
|
||||
*/
|
||||
gsp->fb.wpr2.frts.size = device->chipset == 0x170 ? 0 : 0x100000;
|
||||
gsp->fb.wpr2.frts.addr = ALIGN_DOWN(gsp->fb.bios.addr, 0x20000) - gsp->fb.wpr2.frts.size;
|
||||
|
||||
gsp->fb.wpr2.boot.size = gsp->boot.fw.size;
|
||||
|
|
@ -343,9 +397,12 @@ tu102_gsp_oneinit(struct nvkm_gsp *gsp)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = nvkm_gsp_fwsec_frts(gsp);
|
||||
if (WARN_ON(ret))
|
||||
return ret;
|
||||
/* Only boot FWSEC-FRTS if it actually exists */
|
||||
if (gsp->fb.wpr2.frts.size) {
|
||||
ret = nvkm_gsp_fwsec_frts(gsp);
|
||||
if (WARN_ON(ret))
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Reset GSP into RISC-V mode. */
|
||||
ret = gsp->func->reset(gsp);
|
||||
|
|
|
|||
|
|
@ -2134,6 +2134,7 @@ static const struct edp_panel_entry edp_panels[] = {
|
|||
EDP_PANEL_ENTRY('L', 'G', 'D', 0x0567, &delay_200_500_e200_d200, "Unknown"),
|
||||
EDP_PANEL_ENTRY('L', 'G', 'D', 0x05af, &delay_200_500_e200_d200, "Unknown"),
|
||||
EDP_PANEL_ENTRY('L', 'G', 'D', 0x05f1, &delay_200_500_e200_d200, "Unknown"),
|
||||
EDP_PANEL_ENTRY('L', 'G', 'D', 0x06b2, &delay_200_500_e200_d200, "LP129WT232166"),
|
||||
EDP_PANEL_ENTRY('L', 'G', 'D', 0x0778, &delay_200_500_e200_d200, "134WT1"),
|
||||
EDP_PANEL_ENTRY('L', 'G', 'D', 0x07fe, &delay_200_500_e200_d200, "LP116WHA-SPB1"),
|
||||
|
||||
|
|
|
|||
|
|
@ -820,6 +820,31 @@ static const struct panel_desc ampire_am_1280800n3tzqw_t00h = {
|
|||
.connector_type = DRM_MODE_CONNECTOR_LVDS,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode ampire_am_1280800w8tzqw_t00h_mode = {
|
||||
.clock = 72400,
|
||||
.hdisplay = 1280,
|
||||
.hsync_start = 1280 + 40,
|
||||
.hsync_end = 1280 + 40 + 80,
|
||||
.htotal = 1280 + 40 + 80 + 40,
|
||||
.vdisplay = 800,
|
||||
.vsync_start = 800 + 10,
|
||||
.vsync_end = 800 + 10 + 18,
|
||||
.vtotal = 800 + 10 + 18 + 10,
|
||||
};
|
||||
|
||||
static const struct panel_desc ampire_am_1280800w8tzqw_t00h = {
|
||||
.modes = &ire_am_1280800w8tzqw_t00h_mode,
|
||||
.num_modes = 1,
|
||||
.bpc = 8,
|
||||
.size = {
|
||||
.width = 217,
|
||||
.height = 136,
|
||||
},
|
||||
.bus_flags = DRM_BUS_FLAG_DE_HIGH,
|
||||
.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
|
||||
.connector_type = DRM_MODE_CONNECTOR_LVDS,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode ampire_am_480272h3tmqw_t01h_mode = {
|
||||
.clock = 9000,
|
||||
.hdisplay = 480,
|
||||
|
|
@ -3692,6 +3717,32 @@ static const struct panel_desc nec_nl4827hc19_05b = {
|
|||
.bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode nec_nl6448bc33_70c_mode = {
|
||||
.clock = 25175,
|
||||
.hdisplay = 640,
|
||||
.hsync_start = 640 + 16,
|
||||
.hsync_end = 640 + 16 + 48,
|
||||
.htotal = 640 + 16 + 48 + 96,
|
||||
.vdisplay = 480,
|
||||
.vsync_start = 480 + 2,
|
||||
.vsync_end = 480 + 2 + 31,
|
||||
.vtotal = 480 + 2 + 31 + 31,
|
||||
.flags = DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_PHSYNC,
|
||||
};
|
||||
|
||||
static const struct panel_desc nec_nl6448bc33_70c = {
|
||||
.modes = &nec_nl6448bc33_70c_mode,
|
||||
.num_modes = 1,
|
||||
.bpc = 6,
|
||||
.size = {
|
||||
.width = 211,
|
||||
.height = 158,
|
||||
},
|
||||
.bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG,
|
||||
.bus_flags = DRM_BUS_FLAG_DE_HIGH,
|
||||
.connector_type = DRM_MODE_CONNECTOR_LVDS,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode netron_dy_e231732_mode = {
|
||||
.clock = 66000,
|
||||
.hdisplay = 1024,
|
||||
|
|
@ -5588,6 +5639,9 @@ static const struct of_device_id platform_of_match[] = {
|
|||
{
|
||||
.compatible = "ampire,am-1280800n3tzqw-t00h",
|
||||
.data = &ire_am_1280800n3tzqw_t00h,
|
||||
}, {
|
||||
.compatible = "ampire,am-1280800w8tzqw-t00h",
|
||||
.data = &ire_am_1280800w8tzqw_t00h,
|
||||
}, {
|
||||
.compatible = "ampire,am-480272h3tmqw-t01h",
|
||||
.data = &ire_am_480272h3tmqw_t01h,
|
||||
|
|
@ -5918,6 +5972,9 @@ static const struct of_device_id platform_of_match[] = {
|
|||
}, {
|
||||
.compatible = "nec,nl4827hc19-05b",
|
||||
.data = &nec_nl4827hc19_05b,
|
||||
}, {
|
||||
.compatible = "nec,nl6448bc33-70c",
|
||||
.data = &nec_nl6448bc33_70c,
|
||||
}, {
|
||||
.compatible = "netron-dy,e231732",
|
||||
.data = &netron_dy_e231732,
|
||||
|
|
|
|||
|
|
@ -687,6 +687,8 @@ static void panthor_gem_evict_locked(struct panthor_gem_object *bo)
|
|||
if (drm_WARN_ON_ONCE(bo->base.dev, !bo->backing.pages))
|
||||
return;
|
||||
|
||||
atomic_add_unless(&bo->reclaimed_count, 1, INT_MAX);
|
||||
|
||||
panthor_gem_dev_map_cleanup_locked(bo);
|
||||
panthor_gem_backing_cleanup_locked(bo);
|
||||
panthor_gem_update_reclaim_state_locked(bo, NULL);
|
||||
|
|
@ -1590,6 +1592,7 @@ static void panthor_gem_debugfs_print_flag_names(struct seq_file *m)
|
|||
static const char * const gem_state_flags_names[] = {
|
||||
[PANTHOR_DEBUGFS_GEM_STATE_IMPORTED_BIT] = "imported",
|
||||
[PANTHOR_DEBUGFS_GEM_STATE_EXPORTED_BIT] = "exported",
|
||||
[PANTHOR_DEBUGFS_GEM_STATE_EVICTED_BIT] = "evicted",
|
||||
};
|
||||
|
||||
static const char * const gem_usage_flags_names[] = {
|
||||
|
|
@ -1620,6 +1623,7 @@ static void panthor_gem_debugfs_bo_print(struct panthor_gem_object *bo,
|
|||
{
|
||||
enum panthor_gem_reclaim_state reclaim_state = bo->reclaim_state;
|
||||
unsigned int refcount = kref_read(&bo->base.refcount);
|
||||
int reclaimed_count = atomic_read(&bo->reclaimed_count);
|
||||
char creator_info[32] = {};
|
||||
size_t resident_size;
|
||||
u32 gem_usage_flags = bo->debugfs.flags;
|
||||
|
|
@ -1633,16 +1637,20 @@ static void panthor_gem_debugfs_bo_print(struct panthor_gem_object *bo,
|
|||
|
||||
snprintf(creator_info, sizeof(creator_info),
|
||||
"%s/%d", bo->debugfs.creator.process_name, bo->debugfs.creator.tgid);
|
||||
seq_printf(m, "%-32s%-16d%-16d%-16zd%-16zd0x%-16lx",
|
||||
seq_printf(m, "%-32s%-16d%-11d%-11d%-16zd%-16zd0x%-16lx",
|
||||
creator_info,
|
||||
bo->base.name,
|
||||
refcount,
|
||||
reclaimed_count,
|
||||
bo->base.size,
|
||||
resident_size,
|
||||
drm_vma_node_start(&bo->base.vma_node));
|
||||
|
||||
if (drm_gem_is_imported(&bo->base))
|
||||
gem_state_flags |= PANTHOR_DEBUGFS_GEM_STATE_FLAG_IMPORTED;
|
||||
else if (!resident_size && reclaimed_count)
|
||||
gem_state_flags |= PANTHOR_DEBUGFS_GEM_STATE_FLAG_EVICTED;
|
||||
|
||||
if (bo->base.dma_buf)
|
||||
gem_state_flags |= PANTHOR_DEBUGFS_GEM_STATE_FLAG_EXPORTED;
|
||||
|
||||
|
|
@ -1666,8 +1674,8 @@ static void panthor_gem_debugfs_print_bos(struct panthor_device *ptdev,
|
|||
|
||||
panthor_gem_debugfs_print_flag_names(m);
|
||||
|
||||
seq_puts(m, "created-by global-name refcount size resident-size file-offset state usage label\n");
|
||||
seq_puts(m, "----------------------------------------------------------------------------------------------------------------------------------------------\n");
|
||||
seq_puts(m, "created-by global-name refcount evictions size resident-size file-offset state usage label\n");
|
||||
seq_puts(m, "----------------------------------------------------------------------------------------------------------------------------------------------------\n");
|
||||
|
||||
scoped_guard(mutex, &ptdev->gems.lock) {
|
||||
list_for_each_entry(bo, &ptdev->gems.node, debugfs.node) {
|
||||
|
|
@ -1675,7 +1683,7 @@ static void panthor_gem_debugfs_print_bos(struct panthor_device *ptdev,
|
|||
}
|
||||
}
|
||||
|
||||
seq_puts(m, "==============================================================================================================================================\n");
|
||||
seq_puts(m, "====================================================================================================================================================\n");
|
||||
seq_printf(m, "Total size: %zd, Total resident: %zd, Total reclaimable: %zd\n",
|
||||
totals.size, totals.resident, totals.reclaimable);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,12 +19,16 @@ struct panthor_vm;
|
|||
enum panthor_debugfs_gem_state_flags {
|
||||
PANTHOR_DEBUGFS_GEM_STATE_IMPORTED_BIT = 0,
|
||||
PANTHOR_DEBUGFS_GEM_STATE_EXPORTED_BIT = 1,
|
||||
PANTHOR_DEBUGFS_GEM_STATE_EVICTED_BIT = 2,
|
||||
|
||||
/** @PANTHOR_DEBUGFS_GEM_STATE_FLAG_IMPORTED: GEM BO is PRIME imported. */
|
||||
PANTHOR_DEBUGFS_GEM_STATE_FLAG_IMPORTED = BIT(PANTHOR_DEBUGFS_GEM_STATE_IMPORTED_BIT),
|
||||
|
||||
/** @PANTHOR_DEBUGFS_GEM_STATE_FLAG_EXPORTED: GEM BO is PRIME exported. */
|
||||
PANTHOR_DEBUGFS_GEM_STATE_FLAG_EXPORTED = BIT(PANTHOR_DEBUGFS_GEM_STATE_EXPORTED_BIT),
|
||||
|
||||
/** @PANTHOR_DEBUGFS_GEM_STATE_FLAG_EVICTED: GEM BO is evicted to swap. */
|
||||
PANTHOR_DEBUGFS_GEM_STATE_FLAG_EVICTED = BIT(PANTHOR_DEBUGFS_GEM_STATE_EVICTED_BIT),
|
||||
};
|
||||
|
||||
enum panthor_debugfs_gem_usage_flags {
|
||||
|
|
@ -172,6 +176,12 @@ struct panthor_gem_object {
|
|||
/** @reclaim_state: Cached reclaim state */
|
||||
enum panthor_gem_reclaim_state reclaim_state;
|
||||
|
||||
/**
|
||||
* @reclaimed_count: How many times object has been evicted to swap.
|
||||
* The count saturates at %INT_MAX and will never wrap around to 0.
|
||||
*/
|
||||
atomic_t reclaimed_count;
|
||||
|
||||
/**
|
||||
* @exclusive_vm_root_gem: Root GEM of the exclusive VM this GEM object
|
||||
* is attached to.
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "rzg2l_du_vsp.h"
|
||||
|
||||
#define DU_MCR0 0x00
|
||||
#define DU_MCR0_DPI_EN BIT(0)
|
||||
#define DU_MCR0_DI_EN BIT(8)
|
||||
|
||||
#define DU_DITR0 0x10
|
||||
|
|
@ -217,8 +218,12 @@ static void rzg2l_du_crtc_put(struct rzg2l_du_crtc *rcrtc)
|
|||
static void rzg2l_du_start_stop(struct rzg2l_du_crtc *rcrtc, bool start)
|
||||
{
|
||||
struct rzg2l_du_device *rcdu = rcrtc->dev;
|
||||
u32 val = DU_MCR0_DI_EN;
|
||||
|
||||
writel(start ? DU_MCR0_DI_EN : 0, rcdu->mmio + DU_MCR0);
|
||||
if (start && rzg2l_du_has(rcdu, RZG2L_DU_FEATURE_DPIO_OE))
|
||||
val |= DU_MCR0_DPI_EN;
|
||||
|
||||
writel(start ? val : 0, rcdu->mmio + DU_MCR0);
|
||||
}
|
||||
|
||||
static void rzg2l_du_crtc_start(struct rzg2l_du_crtc *rcrtc)
|
||||
|
|
@ -380,7 +385,7 @@ int rzg2l_du_crtc_create(struct rzg2l_du_device *rcdu)
|
|||
struct drm_plane *primary;
|
||||
int ret;
|
||||
|
||||
rcrtc->rstc = devm_reset_control_get_shared(rcdu->dev, NULL);
|
||||
rcrtc->rstc = devm_reset_control_get_optional_shared(rcdu->dev, NULL);
|
||||
if (IS_ERR(rcrtc->rstc)) {
|
||||
dev_err(rcdu->dev, "can't get cpg reset\n");
|
||||
return PTR_ERR(rcrtc->rstc);
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ static const struct rzg2l_du_device_info rzg2l_du_r9a07g043u_info = {
|
|||
.port = 0,
|
||||
},
|
||||
},
|
||||
.mode_clock_min = 20875,
|
||||
.mode_clock_max = 83500,
|
||||
};
|
||||
|
||||
static const struct rzg2l_du_device_info rzg2l_du_r9a07g044_info = {
|
||||
|
|
@ -48,7 +50,9 @@ static const struct rzg2l_du_device_info rzg2l_du_r9a07g044_info = {
|
|||
.possible_outputs = BIT(0),
|
||||
.port = 1,
|
||||
}
|
||||
}
|
||||
},
|
||||
.mode_clock_min = 20875,
|
||||
.mode_clock_max = 83500,
|
||||
};
|
||||
|
||||
static const struct rzg2l_du_device_info rzg2l_du_r9a09g057_info = {
|
||||
|
|
@ -61,10 +65,24 @@ static const struct rzg2l_du_device_info rzg2l_du_r9a09g057_info = {
|
|||
},
|
||||
};
|
||||
|
||||
static const struct rzg2l_du_device_info rzg2l_du_r9a09g077_info = {
|
||||
.channels_mask = BIT(0),
|
||||
.routes = {
|
||||
[RZG2L_DU_OUTPUT_DPAD0] = {
|
||||
.possible_outputs = BIT(0),
|
||||
.port = 0,
|
||||
},
|
||||
},
|
||||
.features = RZG2L_DU_FEATURE_DPIO_OE,
|
||||
.mode_clock_min = 5000,
|
||||
.mode_clock_max = 100000,
|
||||
};
|
||||
|
||||
static const struct of_device_id rzg2l_du_of_table[] = {
|
||||
{ .compatible = "renesas,r9a07g043u-du", .data = &rzg2l_du_r9a07g043u_info },
|
||||
{ .compatible = "renesas,r9a07g044-du", .data = &rzg2l_du_r9a07g044_info },
|
||||
{ .compatible = "renesas,r9a09g057-du", .data = &rzg2l_du_r9a09g057_info },
|
||||
{ .compatible = "renesas,r9a09g077-du", .data = &rzg2l_du_r9a09g077_info },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
struct device;
|
||||
struct drm_property;
|
||||
|
||||
#define RZG2L_DU_FEATURE_DPIO_OE BIT(0) /* Has DPIO output enable control */
|
||||
|
||||
enum rzg2l_du_output {
|
||||
RZG2L_DU_OUTPUT_DSI0,
|
||||
RZG2L_DU_OUTPUT_DPAD0,
|
||||
|
|
@ -44,10 +46,16 @@ struct rzg2l_du_output_routing {
|
|||
* struct rzg2l_du_device_info - DU model-specific information
|
||||
* @channels_mask: bit mask of available DU channels
|
||||
* @routes: array of CRTC to output routes, indexed by output (RZG2L_DU_OUTPUT_*)
|
||||
* @mode_clock_min: minimum pixel clock in kHz
|
||||
* @mode_clock_max: maximum pixel clock in kHz
|
||||
* @features: device features (RZG2L_DU_FEATURE_*)
|
||||
*/
|
||||
struct rzg2l_du_device_info {
|
||||
unsigned int channels_mask;
|
||||
struct rzg2l_du_output_routing routes[RZG2L_DU_OUTPUT_MAX];
|
||||
u32 mode_clock_min;
|
||||
u32 mode_clock_max;
|
||||
unsigned int features;
|
||||
};
|
||||
|
||||
#define RZG2L_DU_MAX_CRTCS 1
|
||||
|
|
@ -73,6 +81,12 @@ static inline struct rzg2l_du_device *to_rzg2l_du_device(struct drm_device *dev)
|
|||
return container_of(dev, struct rzg2l_du_device, ddev);
|
||||
}
|
||||
|
||||
static inline bool rzg2l_du_has(struct rzg2l_du_device *rcdu,
|
||||
unsigned int feature)
|
||||
{
|
||||
return rcdu->info->features & feature;
|
||||
}
|
||||
|
||||
const char *rzg2l_du_output_name(enum rzg2l_du_output output);
|
||||
|
||||
#endif /* __RZG2L_DU_DRV_H__ */
|
||||
|
|
|
|||
|
|
@ -50,8 +50,15 @@ rzg2l_du_encoder_mode_valid(struct drm_encoder *encoder,
|
|||
const struct drm_display_mode *mode)
|
||||
{
|
||||
struct rzg2l_du_encoder *renc = to_rzg2l_encoder(encoder);
|
||||
struct rzg2l_du_device *rcdu = to_rzg2l_du_device(renc->base.dev);
|
||||
const struct rzg2l_du_device_info *info = rcdu->info;
|
||||
|
||||
if (renc->output == RZG2L_DU_OUTPUT_DPAD0 && mode->clock > 83500)
|
||||
if (renc->output != RZG2L_DU_OUTPUT_DPAD0)
|
||||
return MODE_OK;
|
||||
|
||||
if (mode->clock < info->mode_clock_min)
|
||||
return MODE_CLOCK_LOW;
|
||||
if (mode->clock > info->mode_clock_max)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
return MODE_OK;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,103 @@
|
|||
#include "hub.h"
|
||||
#include "plane.h"
|
||||
|
||||
static const u16 default_srgb_lut[] = {
|
||||
0x6000, 0x60CE, 0x619D, 0x626C, 0x632D, 0x63D4, 0x6469, 0x64F0, 0x656B, 0x65DF, 0x664A,
|
||||
0x66B0, 0x6711, 0x676D, 0x67C4, 0x6819, 0x686A, 0x68B8, 0x6904, 0x694D, 0x6994, 0x69D8,
|
||||
0x6A1B, 0x6A5D, 0x6A9C, 0x6ADA, 0x6B17, 0x6B52, 0x6B8C, 0x6BC5, 0x6BFD, 0x6C33, 0x6C69,
|
||||
0x6C9E, 0x6CD1, 0x6D04, 0x6D36, 0x6D67, 0x6D98, 0x6DC7, 0x6DF6, 0x6E25, 0x6E52, 0x6E7F,
|
||||
0x6EAC, 0x6ED7, 0x6F03, 0x6F2D, 0x6F58, 0x6F81, 0x6FAA, 0x6FD3, 0x6FFB, 0x7023, 0x704B,
|
||||
0x7071, 0x7098, 0x70BE, 0x70E4, 0x7109, 0x712E, 0x7153, 0x7177, 0x719B, 0x71BF, 0x71E2,
|
||||
0x7205, 0x7227, 0x724A, 0x726C, 0x728E, 0x72AF, 0x72D0, 0x72F1, 0x7312, 0x7333, 0x7353,
|
||||
0x7373, 0x7392, 0x73B2, 0x73D1, 0x73F0, 0x740F, 0x742D, 0x744C, 0x746A, 0x7488, 0x74A6,
|
||||
0x74C3, 0x74E0, 0x74FE, 0x751B, 0x7537, 0x7554, 0x7570, 0x758D, 0x75A9, 0x75C4, 0x75E0,
|
||||
0x75FC, 0x7617, 0x7632, 0x764D, 0x7668, 0x7683, 0x769E, 0x76B8, 0x76D3, 0x76ED, 0x7707,
|
||||
0x7721, 0x773B, 0x7754, 0x776E, 0x7787, 0x77A0, 0x77B9, 0x77D2, 0x77EB, 0x7804, 0x781D,
|
||||
0x7835, 0x784E, 0x7866, 0x787E, 0x7896, 0x78AE, 0x78C6, 0x78DD, 0x78F5, 0x790D, 0x7924,
|
||||
0x793B, 0x7952, 0x796A, 0x7981, 0x7997, 0x79AE, 0x79C5, 0x79DB, 0x79F2, 0x7A08, 0x7A1F,
|
||||
0x7A35, 0x7A4B, 0x7A61, 0x7A77, 0x7A8D, 0x7AA3, 0x7AB8, 0x7ACE, 0x7AE3, 0x7AF9, 0x7B0E,
|
||||
0x7B24, 0x7B39, 0x7B4E, 0x7B63, 0x7B78, 0x7B8D, 0x7BA2, 0x7BB6, 0x7BCB, 0x7BE0, 0x7BF4,
|
||||
0x7C08, 0x7C1D, 0x7C31, 0x7C45, 0x7C59, 0x7C6E, 0x7C82, 0x7C96, 0x7CA9, 0x7CBD, 0x7CD1,
|
||||
0x7CE5, 0x7CF8, 0x7D0C, 0x7D1F, 0x7D33, 0x7D46, 0x7D59, 0x7D6D, 0x7D80, 0x7D93, 0x7DA6,
|
||||
0x7DB9, 0x7DCC, 0x7DDF, 0x7DF2, 0x7E04, 0x7E17, 0x7E2A, 0x7E3C, 0x7E4F, 0x7E61, 0x7E74,
|
||||
0x7E86, 0x7E98, 0x7EAB, 0x7EBD, 0x7ECF, 0x7EE1, 0x7EF3, 0x7F05, 0x7F17, 0x7F29, 0x7F3B,
|
||||
0x7F4D, 0x7F5E, 0x7F70, 0x7F82, 0x7F93, 0x7FA5, 0x7FB6, 0x7FC8, 0x7FD9, 0x7FEB, 0x7FFC,
|
||||
0x800D, 0x801E, 0x8030, 0x8041, 0x8052, 0x8063, 0x8074, 0x8085, 0x8096, 0x80A7, 0x80B7,
|
||||
0x80C8, 0x80D9, 0x80EA, 0x80FA, 0x810B, 0x811C, 0x812C, 0x813D, 0x814D, 0x815D, 0x816E,
|
||||
0x817E, 0x818E, 0x819F, 0x81AF, 0x81BF, 0x81CF, 0x81DF, 0x81EF, 0x81FF, 0x820F, 0x821F,
|
||||
0x822F, 0x823F, 0x824F, 0x825F, 0x826F, 0x827E, 0x828E, 0x829E, 0x82AD, 0x82BD, 0x82CC,
|
||||
0x82DC, 0x82EB, 0x82FB, 0x830A, 0x831A, 0x8329, 0x8338, 0x8348, 0x8357, 0x8366, 0x8375,
|
||||
0x8385, 0x8394, 0x83A3, 0x83B2, 0x83C1, 0x83D0, 0x83DF, 0x83EE, 0x83FD, 0x840C, 0x841A,
|
||||
0x8429, 0x8438, 0x8447, 0x8455, 0x8464, 0x8473, 0x8481, 0x8490, 0x849F, 0x84AD, 0x84BC,
|
||||
0x84CA, 0x84D9, 0x84E7, 0x84F5, 0x8504, 0x8512, 0x8521, 0x852F, 0x853D, 0x854B, 0x855A,
|
||||
0x8568, 0x8576, 0x8584, 0x8592, 0x85A0, 0x85AE, 0x85BC, 0x85CA, 0x85D8, 0x85E6, 0x85F4,
|
||||
0x8602, 0x8610, 0x861E, 0x862C, 0x8639, 0x8647, 0x8655, 0x8663, 0x8670, 0x867E, 0x868C,
|
||||
0x8699, 0x86A7, 0x86B5, 0x86C2, 0x86D0, 0x86DD, 0x86EB, 0x86F8, 0x8705, 0x8713, 0x8720,
|
||||
0x872E, 0x873B, 0x8748, 0x8756, 0x8763, 0x8770, 0x877D, 0x878B, 0x8798, 0x87A5, 0x87B2,
|
||||
0x87BF, 0x87CC, 0x87D9, 0x87E6, 0x87F3, 0x8801, 0x880E, 0x881A, 0x8827, 0x8834, 0x8841,
|
||||
0x884E, 0x885B, 0x8868, 0x8875, 0x8882, 0x888E, 0x889B, 0x88A8, 0x88B5, 0x88C1, 0x88CE,
|
||||
0x88DB, 0x88E7, 0x88F4, 0x8900, 0x890D, 0x891A, 0x8926, 0x8933, 0x893F, 0x894C, 0x8958,
|
||||
0x8965, 0x8971, 0x897D, 0x898A, 0x8996, 0x89A3, 0x89AF, 0x89BB, 0x89C8, 0x89D4, 0x89E0,
|
||||
0x89EC, 0x89F9, 0x8A05, 0x8A11, 0x8A1D, 0x8A29, 0x8A36, 0x8A42, 0x8A4E, 0x8A5A, 0x8A66,
|
||||
0x8A72, 0x8A7E, 0x8A8A, 0x8A96, 0x8AA2, 0x8AAE, 0x8ABA, 0x8AC6, 0x8AD2, 0x8ADE, 0x8AEA,
|
||||
0x8AF5, 0x8B01, 0x8B0D, 0x8B19, 0x8B25, 0x8B31, 0x8B3C, 0x8B48, 0x8B54, 0x8B60, 0x8B6B,
|
||||
0x8B77, 0x8B83, 0x8B8E, 0x8B9A, 0x8BA6, 0x8BB1, 0x8BBD, 0x8BC8, 0x8BD4, 0x8BDF, 0x8BEB,
|
||||
0x8BF6, 0x8C02, 0x8C0D, 0x8C19, 0x8C24, 0x8C30, 0x8C3B, 0x8C47, 0x8C52, 0x8C5D, 0x8C69,
|
||||
0x8C74, 0x8C80, 0x8C8B, 0x8C96, 0x8CA1, 0x8CAD, 0x8CB8, 0x8CC3, 0x8CCF, 0x8CDA, 0x8CE5,
|
||||
0x8CF0, 0x8CFB, 0x8D06, 0x8D12, 0x8D1D, 0x8D28, 0x8D33, 0x8D3E, 0x8D49, 0x8D54, 0x8D5F,
|
||||
0x8D6A, 0x8D75, 0x8D80, 0x8D8B, 0x8D96, 0x8DA1, 0x8DAC, 0x8DB7, 0x8DC2, 0x8DCD, 0x8DD8,
|
||||
0x8DE3, 0x8DEE, 0x8DF9, 0x8E04, 0x8E0E, 0x8E19, 0x8E24, 0x8E2F, 0x8E3A, 0x8E44, 0x8E4F,
|
||||
0x8E5A, 0x8E65, 0x8E6F, 0x8E7A, 0x8E85, 0x8E90, 0x8E9A, 0x8EA5, 0x8EB0, 0x8EBA, 0x8EC5,
|
||||
0x8ECF, 0x8EDA, 0x8EE5, 0x8EEF, 0x8EFA, 0x8F04, 0x8F0F, 0x8F19, 0x8F24, 0x8F2E, 0x8F39,
|
||||
0x8F43, 0x8F4E, 0x8F58, 0x8F63, 0x8F6D, 0x8F78, 0x8F82, 0x8F8C, 0x8F97, 0x8FA1, 0x8FAC,
|
||||
0x8FB6, 0x8FC0, 0x8FCB, 0x8FD5, 0x8FDF, 0x8FEA, 0x8FF4, 0x8FFE, 0x9008, 0x9013, 0x901D,
|
||||
0x9027, 0x9031, 0x903C, 0x9046, 0x9050, 0x905A, 0x9064, 0x906E, 0x9079, 0x9083, 0x908D,
|
||||
0x9097, 0x90A1, 0x90AB, 0x90B5, 0x90BF, 0x90C9, 0x90D3, 0x90DD, 0x90E7, 0x90F1, 0x90FB,
|
||||
0x9105, 0x910F, 0x9119, 0x9123, 0x912D, 0x9137, 0x9141, 0x914B, 0x9155, 0x915F, 0x9169,
|
||||
0x9173, 0x917D, 0x9186, 0x9190, 0x919A, 0x91A4, 0x91AE, 0x91B8, 0x91C1, 0x91CB, 0x91D5,
|
||||
0x91DF, 0x91E9, 0x91F2, 0x91FC, 0x9206, 0x9210, 0x9219, 0x9223, 0x922D, 0x9236, 0x9240,
|
||||
0x924A, 0x9253, 0x925D, 0x9267, 0x9270, 0x927A, 0x9283, 0x928D, 0x9297, 0x92A0, 0x92AA,
|
||||
0x92B3, 0x92BD, 0x92C6, 0x92D0, 0x92DA, 0x92E3, 0x92ED, 0x92F6, 0x9300, 0x9309, 0x9313,
|
||||
0x931C, 0x9325, 0x932F, 0x9338, 0x9342, 0x934B, 0x9355, 0x935E, 0x9367, 0x9371, 0x937A,
|
||||
0x9384, 0x938D, 0x9396, 0x93A0, 0x93A9, 0x93B2, 0x93BC, 0x93C5, 0x93CE, 0x93D7, 0x93E1,
|
||||
0x93EA, 0x93F3, 0x93FC, 0x9406, 0x940F, 0x9418, 0x9421, 0x942B, 0x9434, 0x943D, 0x9446,
|
||||
0x944F, 0x9459, 0x9462, 0x946B, 0x9474, 0x947D, 0x9486, 0x948F, 0x9499, 0x94A2, 0x94AB,
|
||||
0x94B4, 0x94BD, 0x94C6, 0x94CF, 0x94D8, 0x94E1, 0x94EA, 0x94F3, 0x94FC, 0x9505, 0x950E,
|
||||
0x9517, 0x9520, 0x9529, 0x9532, 0x953B, 0x9544, 0x954D, 0x9556, 0x955F, 0x9568, 0x9571,
|
||||
0x957A, 0x9583, 0x958C, 0x9595, 0x959D, 0x95A6, 0x95AF, 0x95B8, 0x95C1, 0x95CA, 0x95D3,
|
||||
0x95DB, 0x95E4, 0x95ED, 0x95F6, 0x95FF, 0x9608, 0x9610, 0x9619, 0x9622, 0x962B, 0x9633,
|
||||
0x963C, 0x9645, 0x964E, 0x9656, 0x965F, 0x9668, 0x9671, 0x9679, 0x9682, 0x968B, 0x9693,
|
||||
0x969C, 0x96A5, 0x96AD, 0x96B6, 0x96BF, 0x96C7, 0x96D0, 0x96D9, 0x96E1, 0x96EA, 0x96F2,
|
||||
0x96FB, 0x9704, 0x970C, 0x9715, 0x971D, 0x9726, 0x972E, 0x9737, 0x9740, 0x9748, 0x9751,
|
||||
0x9759, 0x9762, 0x976A, 0x9773, 0x977B, 0x9784, 0x978C, 0x9795, 0x979D, 0x97A6, 0x97AE,
|
||||
0x97B6, 0x97BF, 0x97C7, 0x97D0, 0x97D8, 0x97E1, 0x97E9, 0x97F1, 0x97FA, 0x9802, 0x980B,
|
||||
0x9813, 0x981B, 0x9824, 0x982C, 0x9834, 0x983D, 0x9845, 0x984D, 0x9856, 0x985E, 0x9866,
|
||||
0x986F, 0x9877, 0x987F, 0x9888, 0x9890, 0x9898, 0x98A0, 0x98A9, 0x98B1, 0x98B9, 0x98C1,
|
||||
0x98CA, 0x98D2, 0x98DA, 0x98E2, 0x98EB, 0x98F3, 0x98FB, 0x9903, 0x990B, 0x9914, 0x991C,
|
||||
0x9924, 0x992C, 0x9934, 0x993C, 0x9945, 0x994D, 0x9955, 0x995D, 0x9965, 0x996D, 0x9975,
|
||||
0x997D, 0x9986, 0x998E, 0x9996, 0x999E, 0x99A6, 0x99AE, 0x99B6, 0x99BE, 0x99C6, 0x99CE,
|
||||
0x99D6, 0x99DE, 0x99E6, 0x99EE, 0x99F6, 0x99FE, 0x9A06, 0x9A0E, 0x9A16, 0x9A1E, 0x9A26,
|
||||
0x9A2E, 0x9A36, 0x9A3E, 0x9A46, 0x9A4E, 0x9A56, 0x9A5E, 0x9A66, 0x9A6E, 0x9A76, 0x9A7E,
|
||||
0x9A86, 0x9A8E, 0x9A96, 0x9A9D, 0x9AA5, 0x9AAD, 0x9AB5, 0x9ABD, 0x9AC5, 0x9ACD, 0x9AD5,
|
||||
0x9ADC, 0x9AE4, 0x9AEC, 0x9AF4, 0x9AFC, 0x9B04, 0x9B0C, 0x9B13, 0x9B1B, 0x9B23, 0x9B2B,
|
||||
0x9B33, 0x9B3A, 0x9B42, 0x9B4A, 0x9B52, 0x9B59, 0x9B61, 0x9B69, 0x9B71, 0x9B79, 0x9B80,
|
||||
0x9B88, 0x9B90, 0x9B97, 0x9B9F, 0x9BA7, 0x9BAF, 0x9BB6, 0x9BBE, 0x9BC6, 0x9BCD, 0x9BD5,
|
||||
0x9BDD, 0x9BE5, 0x9BEC, 0x9BF4, 0x9BFC, 0x9C03, 0x9C0B, 0x9C12, 0x9C1A, 0x9C22, 0x9C29,
|
||||
0x9C31, 0x9C39, 0x9C40, 0x9C48, 0x9C50, 0x9C57, 0x9C5F, 0x9C66, 0x9C6E, 0x9C75, 0x9C7D,
|
||||
0x9C85, 0x9C8C, 0x9C94, 0x9C9B, 0x9CA3, 0x9CAA, 0x9CB2, 0x9CBA, 0x9CC1, 0x9CC9, 0x9CD0,
|
||||
0x9CD8, 0x9CDF, 0x9CE7, 0x9CEE, 0x9CF6, 0x9CFD, 0x9D05, 0x9D0C, 0x9D14, 0x9D1B, 0x9D23,
|
||||
0x9D2A, 0x9D32, 0x9D39, 0x9D40, 0x9D48, 0x9D4F, 0x9D57, 0x9D5E, 0x9D66, 0x9D6D, 0x9D75,
|
||||
0x9D7C, 0x9D83, 0x9D8B, 0x9D92, 0x9D9A, 0x9DA1, 0x9DA8, 0x9DB0, 0x9DB7, 0x9DBE, 0x9DC6,
|
||||
0x9DCD, 0x9DD5, 0x9DDC, 0x9DE3, 0x9DEB, 0x9DF2, 0x9DF9, 0x9E01, 0x9E08, 0x9E0F, 0x9E17,
|
||||
0x9E1E, 0x9E25, 0x9E2D, 0x9E34, 0x9E3B, 0x9E43, 0x9E4A, 0x9E51, 0x9E58, 0x9E60, 0x9E67,
|
||||
0x9E6E, 0x9E75, 0x9E7D, 0x9E84, 0x9E8B, 0x9E92, 0x9E9A, 0x9EA1, 0x9EA8, 0x9EAF, 0x9EB7,
|
||||
0x9EBE, 0x9EC5, 0x9ECC, 0x9ED4, 0x9EDB, 0x9EE2, 0x9EE9, 0x9EF0, 0x9EF7, 0x9EFF, 0x9F06,
|
||||
0x9F0D, 0x9F14, 0x9F1B, 0x9F23, 0x9F2A, 0x9F31, 0x9F38, 0x9F3F, 0x9F46, 0x9F4D, 0x9F55,
|
||||
0x9F5C, 0x9F63, 0x9F6A, 0x9F71, 0x9F78, 0x9F7F, 0x9F86, 0x9F8D, 0x9F95, 0x9F9C, 0x9FA3,
|
||||
0x9FAA, 0x9FB1, 0x9FB8, 0x9FBF, 0x9FC6, 0x9FCD, 0x9FD4, 0x9FDB, 0x9FE2, 0x9FE9, 0x9FF0,
|
||||
0x9FF7, 0x9FFF,
|
||||
};
|
||||
|
||||
static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *state);
|
||||
|
||||
|
|
@ -101,8 +198,10 @@ bool tegra_dc_has_output(struct tegra_dc *dc, struct device *dev)
|
|||
int err;
|
||||
|
||||
of_for_each_phandle(&it, err, np, "nvidia,outputs", NULL, 0)
|
||||
if (it.node == dev->of_node)
|
||||
if (it.node == dev->of_node) {
|
||||
of_node_put(it.node);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -3251,6 +3350,25 @@ static int tegra_dc_probe(struct platform_device *pdev)
|
|||
if (dc->irq < 0)
|
||||
return -ENXIO;
|
||||
|
||||
if (dc->soc->has_nvdisplay) {
|
||||
unsigned int i;
|
||||
u64 r;
|
||||
|
||||
dc->cmu_output_lut =
|
||||
dmam_alloc_coherent(dc->dev, ARRAY_SIZE(default_srgb_lut) * sizeof(u64),
|
||||
&dc->cmu_output_lut_phys, GFP_KERNEL);
|
||||
|
||||
if (!dc->cmu_output_lut) {
|
||||
dev_err(dc->dev, "failed to allocate lut for cmu\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(default_srgb_lut); i++) {
|
||||
r = default_srgb_lut[i];
|
||||
dc->cmu_output_lut[i] = (r << 32) | (r << 16) | r;
|
||||
}
|
||||
}
|
||||
|
||||
err = tegra_dc_rgb_probe(dc);
|
||||
if (err < 0 && err != -ENODEV)
|
||||
return dev_err_probe(&pdev->dev, err,
|
||||
|
|
|
|||
|
|
@ -103,6 +103,9 @@ struct tegra_dc {
|
|||
const struct tegra_dc_soc_info *soc;
|
||||
|
||||
bool has_opp_table;
|
||||
|
||||
u64 *cmu_output_lut;
|
||||
dma_addr_t cmu_output_lut_phys;
|
||||
};
|
||||
|
||||
static inline struct tegra_dc *
|
||||
|
|
@ -447,6 +450,7 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
|
|||
#define BASE_COLOR_SIZE_888 ( 8 << 0)
|
||||
#define BASE_COLOR_SIZE_101010 ( 10 << 0)
|
||||
#define BASE_COLOR_SIZE_121212 ( 12 << 0)
|
||||
#define CMU_ENABLE_ENABLE (1 << 20)
|
||||
|
||||
#define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431
|
||||
#define SC1_H_QUALIFIER_NONE (1 << 16)
|
||||
|
|
@ -732,6 +736,15 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
|
|||
#define PROTOCOL_MASK (0xf << 8)
|
||||
#define PROTOCOL_SINGLE_TMDS_A (0x1 << 8)
|
||||
|
||||
#define DC_DISP_CORE_HEAD_SET_CONTROL_OUTPUT_LUT 0x431
|
||||
#define OUTPUT_LUT_MODE_MASK (3 << 5)
|
||||
#define OUTPUT_LUT_MODE_INTERPOLATE (1 << 5)
|
||||
#define OUTPUT_LUT_SIZE_MASK (3 << 1)
|
||||
#define OUTPUT_LUT_SIZE_SIZE_1025 (2 << 1)
|
||||
|
||||
#define DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE 0x432
|
||||
#define DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI 0x433
|
||||
|
||||
#define DC_DISP_PCALC_HEAD_SET_CROPPED_POINT_IN_CURSOR 0x442
|
||||
#define DC_DISP_PCALC_HEAD_SET_CROPPED_SIZE_IN_CURSOR 0x446
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
* Copyright (C) 2015 Rob Clark
|
||||
*/
|
||||
|
||||
#include <linux/string_choices.h>
|
||||
|
||||
#include <drm/display/drm_dp_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
|
@ -668,7 +670,7 @@ static int drm_dp_link_train_full(struct drm_dp_link *link)
|
|||
|
||||
retry:
|
||||
DRM_DEBUG_KMS("full-training link: %u lane%s at %u MHz\n",
|
||||
link->lanes, (link->lanes > 1) ? "s" : "",
|
||||
link->lanes, str_plural(link->lanes),
|
||||
link->rate / 100);
|
||||
|
||||
err = drm_dp_link_configure(link->aux, link);
|
||||
|
|
@ -724,7 +726,7 @@ static int drm_dp_link_train_fast(struct drm_dp_link *link)
|
|||
int err;
|
||||
|
||||
DRM_DEBUG_KMS("fast-training link: %u lane%s at %u MHz\n",
|
||||
link->lanes, (link->lanes > 1) ? "s" : "",
|
||||
link->lanes, str_plural(link->lanes),
|
||||
link->rate / 100);
|
||||
|
||||
err = drm_dp_link_configure(link->aux, link);
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ struct drm_dp_link_caps {
|
|||
bool enhanced_framing;
|
||||
|
||||
/**
|
||||
* tps3_supported:
|
||||
* @tps3_supported:
|
||||
*
|
||||
* training pattern sequence 3 supported for equalization
|
||||
*/
|
||||
|
|
@ -62,12 +62,12 @@ void drm_dp_link_caps_copy(struct drm_dp_link_caps *dest,
|
|||
*/
|
||||
struct drm_dp_link_ops {
|
||||
/**
|
||||
* @apply_training:
|
||||
* @apply_training: apply the link training
|
||||
*/
|
||||
int (*apply_training)(struct drm_dp_link *link);
|
||||
|
||||
/**
|
||||
* @configure:
|
||||
* @configure: configure the DP link
|
||||
*/
|
||||
int (*configure)(struct drm_dp_link *link);
|
||||
};
|
||||
|
|
@ -113,6 +113,8 @@ struct drm_dp_link_train {
|
|||
* @max_lanes: maximum number of lanes supported on the link
|
||||
* @caps: capabilities supported on the link (see &drm_dp_link_caps)
|
||||
* @aux_rd_interval: AUX read interval to use for training (in microseconds)
|
||||
* @aux_rd_interval.cr: clock recovery read interval
|
||||
* @aux_rd_interval.ce: channel equalization read interval
|
||||
* @edp: eDP revision (0x11: eDP 1.1, 0x12: eDP 1.2, ...)
|
||||
* @rate: currently configured link rate
|
||||
* @lanes: currently configured number of lanes
|
||||
|
|
@ -126,10 +128,6 @@ struct drm_dp_link {
|
|||
|
||||
struct drm_dp_link_caps caps;
|
||||
|
||||
/**
|
||||
* @cr: clock recovery read interval
|
||||
* @ce: channel equalization read interval
|
||||
*/
|
||||
struct {
|
||||
unsigned int cr;
|
||||
unsigned int ce;
|
||||
|
|
|
|||
|
|
@ -184,11 +184,6 @@ struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
|
|||
bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer);
|
||||
int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer,
|
||||
struct tegra_bo_tiling *tiling);
|
||||
struct drm_framebuffer *tegra_fb_alloc(struct drm_device *drm,
|
||||
const struct drm_format_info *info,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct tegra_bo **planes,
|
||||
unsigned int num_planes);
|
||||
struct drm_framebuffer *tegra_fb_create(struct drm_device *drm,
|
||||
struct drm_file *file,
|
||||
const struct drm_format_info *info,
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ static const struct drm_framebuffer_funcs tegra_fb_funcs = {
|
|||
.create_handle = drm_gem_fb_create_handle,
|
||||
};
|
||||
|
||||
static
|
||||
struct drm_framebuffer *tegra_fb_alloc(struct drm_device *drm,
|
||||
const struct drm_format_info *info,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
|
|
|
|||
|
|
@ -40,8 +40,7 @@ static int tegra_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
|
|||
static void tegra_fbdev_fb_destroy(struct fb_info *info)
|
||||
{
|
||||
struct drm_fb_helper *helper = info->par;
|
||||
struct drm_framebuffer *fb = helper->fb;
|
||||
struct tegra_bo *bo = tegra_fb_get_plane(fb, 0);
|
||||
struct tegra_bo *bo = tegra_fb_get_plane(helper->fb, 0);
|
||||
|
||||
drm_fb_helper_fini(helper);
|
||||
|
||||
|
|
@ -50,8 +49,8 @@ static void tegra_fbdev_fb_destroy(struct fb_info *info)
|
|||
vunmap(bo->vaddr);
|
||||
bo->vaddr = NULL;
|
||||
}
|
||||
drm_framebuffer_remove(fb);
|
||||
|
||||
drm_client_buffer_delete(helper->buffer);
|
||||
drm_client_release(&helper->client);
|
||||
}
|
||||
|
||||
|
|
@ -70,74 +69,79 @@ static const struct drm_fb_helper_funcs tegra_fbdev_helper_funcs = {
|
|||
int tegra_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
|
||||
struct drm_fb_helper_surface_size *sizes)
|
||||
{
|
||||
struct tegra_drm *tegra = helper->dev->dev_private;
|
||||
struct drm_device *drm = helper->dev;
|
||||
struct drm_mode_fb_cmd2 cmd = { 0 };
|
||||
struct drm_client_dev *client = &helper->client;
|
||||
struct drm_device *drm = client->dev;
|
||||
struct drm_file *file = client->file;
|
||||
struct tegra_drm *tegra = drm->dev_private;
|
||||
struct fb_info *info = helper->info;
|
||||
unsigned int bytes_per_pixel;
|
||||
struct drm_framebuffer *fb;
|
||||
unsigned long offset;
|
||||
u32 fourcc, pitch;
|
||||
u64 size;
|
||||
const struct drm_format_info *format;
|
||||
struct tegra_bo *bo;
|
||||
size_t size;
|
||||
struct drm_gem_object *gem;
|
||||
u32 handle;
|
||||
struct drm_client_buffer *buffer;
|
||||
int err;
|
||||
|
||||
bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
|
||||
|
||||
cmd.width = sizes->surface_width;
|
||||
cmd.height = sizes->surface_height;
|
||||
cmd.pitches[0] = round_up(sizes->surface_width * bytes_per_pixel,
|
||||
tegra->pitch_align);
|
||||
|
||||
cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
|
||||
sizes->surface_depth);
|
||||
|
||||
size = cmd.pitches[0] * cmd.height;
|
||||
fourcc = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth);
|
||||
format = drm_get_format_info(drm, fourcc, DRM_FORMAT_MOD_LINEAR);
|
||||
pitch = round_up(drm_format_info_min_pitch(format, 0, sizes->surface_width),
|
||||
tegra->pitch_align);
|
||||
size = ALIGN(pitch * sizes->surface_height, PAGE_SIZE);
|
||||
|
||||
bo = tegra_bo_create(drm, size, 0);
|
||||
if (IS_ERR(bo))
|
||||
return PTR_ERR(bo);
|
||||
gem = &bo->gem;
|
||||
|
||||
fb = tegra_fb_alloc(drm,
|
||||
drm_get_format_info(drm, cmd.pixel_format, cmd.modifier[0]),
|
||||
&cmd, &bo, 1);
|
||||
if (IS_ERR(fb)) {
|
||||
err = PTR_ERR(fb);
|
||||
dev_err(drm->dev, "failed to allocate DRM framebuffer: %d\n",
|
||||
err);
|
||||
drm_gem_object_put(&bo->gem);
|
||||
return PTR_ERR(fb);
|
||||
err = drm_gem_handle_create(file, gem, &handle);
|
||||
if (err)
|
||||
goto err_drm_gem_object_put;
|
||||
|
||||
buffer = drm_client_buffer_create(client, sizes->surface_width, sizes->surface_height,
|
||||
fourcc, handle, pitch);
|
||||
if (IS_ERR(buffer)) {
|
||||
err = PTR_ERR(buffer);
|
||||
goto err_drm_gem_handle_delete;
|
||||
}
|
||||
|
||||
helper->funcs = &tegra_fbdev_helper_funcs;
|
||||
helper->fb = fb;
|
||||
helper->info = info;
|
||||
helper->buffer = buffer;
|
||||
helper->fb = buffer->fb;
|
||||
|
||||
info->fbops = &tegra_fb_ops;
|
||||
|
||||
drm_fb_helper_fill_info(info, helper, sizes);
|
||||
|
||||
offset = info->var.xoffset * bytes_per_pixel +
|
||||
info->var.yoffset * fb->pitches[0];
|
||||
|
||||
if (bo->pages) {
|
||||
bo->vaddr = vmap(bo->pages, bo->num_pages, VM_MAP,
|
||||
pgprot_writecombine(PAGE_KERNEL));
|
||||
if (!bo->vaddr) {
|
||||
dev_err(drm->dev, "failed to vmap() framebuffer\n");
|
||||
err = -ENOMEM;
|
||||
goto destroy;
|
||||
goto err_drm_client_buffer_delete;
|
||||
}
|
||||
}
|
||||
|
||||
info->flags |= FBINFO_VIRTFB;
|
||||
info->screen_buffer = bo->vaddr + offset;
|
||||
info->screen_size = size;
|
||||
info->fix.smem_start = (unsigned long)(bo->iova + offset);
|
||||
info->fix.smem_len = size;
|
||||
info->screen_buffer = bo->vaddr;
|
||||
info->screen_size = gem->size;
|
||||
info->fix.smem_start = (unsigned long)(bo->iova);
|
||||
info->fix.smem_len = gem->size;
|
||||
|
||||
/* The handle is only needed for creating the framebuffer. */
|
||||
drm_gem_handle_delete(file, handle);
|
||||
|
||||
/* The framebuffer still holds a reference on the GEM object. */
|
||||
drm_gem_object_put(gem);
|
||||
|
||||
return 0;
|
||||
|
||||
destroy:
|
||||
drm_framebuffer_remove(fb);
|
||||
err_drm_client_buffer_delete:
|
||||
drm_client_buffer_delete(buffer);
|
||||
err_drm_gem_handle_delete:
|
||||
drm_gem_handle_delete(file, handle);
|
||||
err_drm_gem_object_put:
|
||||
drm_gem_object_put(gem);
|
||||
return err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ static struct host1x_bo_mapping *tegra_bo_pin(struct device *dev, struct host1x_
|
|||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
kref_init(&map->ref);
|
||||
map->bo = host1x_bo_get(bo);
|
||||
map->bo = bo;
|
||||
map->direction = direction;
|
||||
map->dev = dev;
|
||||
|
||||
|
|
@ -170,7 +170,6 @@ static void tegra_bo_unpin(struct host1x_bo_mapping *map)
|
|||
kfree(map->sgt);
|
||||
}
|
||||
|
||||
host1x_bo_put(map->bo);
|
||||
kfree(map);
|
||||
}
|
||||
|
||||
|
|
@ -235,6 +234,7 @@ static const struct host1x_bo_ops tegra_bo_ops = {
|
|||
static int tegra_bo_iommu_map(struct tegra_drm *tegra, struct tegra_bo *bo)
|
||||
{
|
||||
int prot = IOMMU_READ | IOMMU_WRITE;
|
||||
ssize_t size;
|
||||
int err;
|
||||
|
||||
if (bo->mm)
|
||||
|
|
@ -256,13 +256,15 @@ static int tegra_bo_iommu_map(struct tegra_drm *tegra, struct tegra_bo *bo)
|
|||
|
||||
bo->iova = bo->mm->start;
|
||||
|
||||
bo->size = iommu_map_sgtable(tegra->domain, bo->iova, bo->sgt, prot);
|
||||
if (!bo->size) {
|
||||
size = iommu_map_sgtable(tegra->domain, bo->iova, bo->sgt, prot);
|
||||
if (size < 0) {
|
||||
dev_err(tegra->drm->dev, "failed to map buffer\n");
|
||||
err = -ENOMEM;
|
||||
err = size;
|
||||
goto remove;
|
||||
}
|
||||
|
||||
bo->size = size;
|
||||
|
||||
mutex_unlock(&tegra->mm_lock);
|
||||
|
||||
return 0;
|
||||
|
|
@ -509,17 +511,9 @@ static struct tegra_bo *tegra_bo_import(struct drm_device *drm,
|
|||
void tegra_bo_free_object(struct drm_gem_object *gem)
|
||||
{
|
||||
struct tegra_drm *tegra = gem->dev->dev_private;
|
||||
struct host1x_bo_mapping *mapping, *tmp;
|
||||
struct tegra_bo *bo = to_tegra_bo(gem);
|
||||
|
||||
/* remove all mappings of this buffer object from any caches */
|
||||
list_for_each_entry_safe(mapping, tmp, &bo->base.mappings, list) {
|
||||
if (mapping->cache)
|
||||
host1x_bo_unpin(mapping);
|
||||
else
|
||||
dev_err(gem->dev->dev, "mapping %p stale for device %s\n", mapping,
|
||||
dev_name(mapping->dev));
|
||||
}
|
||||
host1x_bo_clear_cached_mappings(&bo->base);
|
||||
|
||||
if (tegra->domain) {
|
||||
tegra_bo_iommu_unmap(tegra, bo);
|
||||
|
|
|
|||
|
|
@ -100,9 +100,6 @@ static int gr2d_exit(struct host1x_client *client)
|
|||
if (err < 0)
|
||||
return err;
|
||||
|
||||
pm_runtime_dont_use_autosuspend(client->dev);
|
||||
pm_runtime_force_suspend(client->dev);
|
||||
|
||||
host1x_client_iommu_detach(client);
|
||||
host1x_syncpt_put(client->syncpts[0]);
|
||||
host1x_channel_put(gr2d->channel);
|
||||
|
|
@ -276,15 +273,21 @@ static int gr2d_probe(struct platform_device *pdev)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
/* initialize address register map */
|
||||
for (i = 0; i < ARRAY_SIZE(gr2d_addr_regs); i++)
|
||||
set_bit(gr2d_addr_regs[i], gr2d->addr_regs);
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
err = host1x_client_register(&gr2d->client.base);
|
||||
if (err < 0) {
|
||||
pm_runtime_disable(dev);
|
||||
dev_err(dev, "failed to register host1x client: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* initialize address register map */
|
||||
for (i = 0; i < ARRAY_SIZE(gr2d_addr_regs); i++)
|
||||
set_bit(gr2d_addr_regs[i], gr2d->addr_regs);
|
||||
pm_runtime_use_autosuspend(dev);
|
||||
pm_runtime_set_autosuspend_delay(dev, 500);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -367,10 +370,6 @@ static int __maybe_unused gr2d_runtime_resume(struct device *dev)
|
|||
goto disable_clk;
|
||||
}
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_use_autosuspend(dev);
|
||||
pm_runtime_set_autosuspend_delay(dev, 500);
|
||||
|
||||
return 0;
|
||||
|
||||
disable_clk:
|
||||
|
|
|
|||
|
|
@ -109,9 +109,6 @@ static int gr3d_exit(struct host1x_client *client)
|
|||
if (err < 0)
|
||||
return err;
|
||||
|
||||
pm_runtime_dont_use_autosuspend(client->dev);
|
||||
pm_runtime_force_suspend(client->dev);
|
||||
|
||||
host1x_client_iommu_detach(client);
|
||||
host1x_syncpt_put(client->syncpts[0]);
|
||||
host1x_channel_put(gr3d->channel);
|
||||
|
|
@ -506,16 +503,22 @@ static int gr3d_probe(struct platform_device *pdev)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
/* initialize address register map */
|
||||
for (i = 0; i < ARRAY_SIZE(gr3d_addr_regs); i++)
|
||||
set_bit(gr3d_addr_regs[i], gr3d->addr_regs);
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
err = host1x_client_register(&gr3d->client.base);
|
||||
if (err < 0) {
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
dev_err(&pdev->dev, "failed to register host1x client: %d\n",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* initialize address register map */
|
||||
for (i = 0; i < ARRAY_SIZE(gr3d_addr_regs); i++)
|
||||
set_bit(gr3d_addr_regs[i], gr3d->addr_regs);
|
||||
pm_runtime_use_autosuspend(&pdev->dev);
|
||||
pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -578,10 +581,6 @@ static int __maybe_unused gr3d_runtime_resume(struct device *dev)
|
|||
goto disable_clk;
|
||||
}
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_use_autosuspend(dev);
|
||||
pm_runtime_set_autosuspend_delay(dev, 500);
|
||||
|
||||
return 0;
|
||||
|
||||
disable_clk:
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@
|
|||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_debugfs.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_encoder.h>
|
||||
#include <drm/drm_eld.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_simple_kms_helper.h>
|
||||
|
||||
#include "hda.h"
|
||||
#include "hdmi.h"
|
||||
|
|
@ -372,6 +372,10 @@ static const struct tmds_config tegra124_tmds_config[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static const struct drm_encoder_funcs tegra_hdmi_encoder_funcs = {
|
||||
.destroy = drm_encoder_cleanup,
|
||||
};
|
||||
|
||||
static void tegra_hdmi_audio_lock(struct tegra_hdmi *hdmi)
|
||||
{
|
||||
mutex_lock(&hdmi->audio_lock);
|
||||
|
|
@ -1555,8 +1559,8 @@ static int tegra_hdmi_init(struct host1x_client *client)
|
|||
|
||||
hdmi->output.dev = client->dev;
|
||||
|
||||
drm_simple_encoder_init(drm, &hdmi->output.encoder,
|
||||
DRM_MODE_ENCODER_TMDS);
|
||||
drm_encoder_init(drm, &hdmi->output.encoder, &tegra_hdmi_encoder_funcs,
|
||||
DRM_MODE_ENCODER_TMDS, NULL);
|
||||
drm_encoder_helper_add(&hdmi->output.encoder,
|
||||
&tegra_hdmi_encoder_helper_funcs);
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/string_choices.h>
|
||||
|
||||
#include <soc/tegra/pmc.h>
|
||||
|
||||
|
|
@ -22,10 +23,10 @@
|
|||
#include <drm/drm_debugfs.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_eld.h>
|
||||
#include <drm/drm_encoder.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_simple_kms_helper.h>
|
||||
|
||||
#include "dc.h"
|
||||
#include "dp.h"
|
||||
|
|
@ -940,7 +941,7 @@ static int tegra_sor_dp_link_configure(struct drm_dp_link *link)
|
|||
err = tegra_sor_power_up_lanes(sor, lanes);
|
||||
if (err < 0) {
|
||||
dev_err(sor->dev, "failed to power up %u lane%s: %d\n",
|
||||
lanes, (lanes != 1) ? "s" : "", err);
|
||||
lanes, str_plural(lanes), err);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -2557,6 +2558,17 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
|
|||
value = tegra_dc_readl(dc, DC_DISP_DISP_COLOR_CONTROL);
|
||||
value &= ~DITHER_CONTROL_MASK;
|
||||
value &= ~BASE_COLOR_SIZE_MASK;
|
||||
if (dc->soc->has_nvdisplay) {
|
||||
tegra_dc_writel(dc, lower_32_bits(dc->cmu_output_lut_phys),
|
||||
DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE);
|
||||
tegra_dc_writel(dc, upper_32_bits(dc->cmu_output_lut_phys),
|
||||
DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI);
|
||||
|
||||
tegra_dc_writel(dc, OUTPUT_LUT_MODE_INTERPOLATE | OUTPUT_LUT_SIZE_SIZE_1025,
|
||||
DC_DISP_CORE_HEAD_SET_CONTROL_OUTPUT_LUT);
|
||||
|
||||
value |= CMU_ENABLE_ENABLE;
|
||||
}
|
||||
|
||||
switch (state->bpc) {
|
||||
case 6:
|
||||
|
|
@ -2921,6 +2933,20 @@ static void tegra_sor_dp_enable(struct drm_encoder *encoder)
|
|||
if (err < 0)
|
||||
dev_err(sor->dev, "failed to attach SOR: %d\n", err);
|
||||
|
||||
if (dc->soc->has_nvdisplay) {
|
||||
value = tegra_dc_readl(dc, DC_DISP_DISP_COLOR_CONTROL);
|
||||
tegra_dc_writel(dc, lower_32_bits(dc->cmu_output_lut_phys),
|
||||
DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE);
|
||||
tegra_dc_writel(dc, upper_32_bits(dc->cmu_output_lut_phys),
|
||||
DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI);
|
||||
|
||||
tegra_dc_writel(dc, OUTPUT_LUT_MODE_INTERPOLATE | OUTPUT_LUT_SIZE_SIZE_1025,
|
||||
DC_DISP_CORE_HEAD_SET_CONTROL_OUTPUT_LUT);
|
||||
|
||||
value |= CMU_ENABLE_ENABLE;
|
||||
tegra_dc_writel(dc, value, DC_DISP_DISP_COLOR_CONTROL);
|
||||
}
|
||||
|
||||
value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
|
||||
value |= SOR_ENABLE(sor->index);
|
||||
tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
|
||||
|
|
@ -3038,6 +3064,10 @@ static const struct tegra_sor_ops tegra_sor_dp_ops = {
|
|||
.probe = tegra_sor_dp_probe,
|
||||
};
|
||||
|
||||
static const struct drm_encoder_funcs tegra_sor_encoder_funcs_cleanup = {
|
||||
.destroy = drm_encoder_cleanup,
|
||||
};
|
||||
|
||||
static int tegra_sor_init(struct host1x_client *client)
|
||||
{
|
||||
struct drm_device *drm = dev_get_drvdata(client->host);
|
||||
|
|
@ -3081,7 +3111,8 @@ static int tegra_sor_init(struct host1x_client *client)
|
|||
&tegra_sor_connector_helper_funcs);
|
||||
sor->output.connector.dpms = DRM_MODE_DPMS_OFF;
|
||||
|
||||
drm_simple_encoder_init(drm, &sor->output.encoder, encoder);
|
||||
drm_encoder_init(drm, &sor->output.encoder,
|
||||
&tegra_sor_encoder_funcs_cleanup, encoder, NULL);
|
||||
drm_encoder_helper_add(&sor->output.encoder, helpers);
|
||||
|
||||
drm_connector_attach_encoder(&sor->output.connector,
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ gather_bo_pin(struct device *dev, struct host1x_bo *bo, enum dma_data_direction
|
|||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
kref_init(&map->ref);
|
||||
map->bo = host1x_bo_get(bo);
|
||||
map->bo = bo;
|
||||
map->direction = direction;
|
||||
map->dev = dev;
|
||||
|
||||
|
|
@ -117,7 +117,6 @@ static void gather_bo_unpin(struct host1x_bo_mapping *map)
|
|||
dma_unmap_sgtable(map->dev, map->sgt, map->direction, 0);
|
||||
sg_free_table(map->sgt);
|
||||
kfree(map->sgt);
|
||||
host1x_bo_put(map->bo);
|
||||
|
||||
kfree(map);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
verisilicon-dc-objs := vs_bridge.o vs_crtc.o vs_dc.o vs_drm.o vs_hwdb.o vs_plane.o vs_primary_plane.o
|
||||
verisilicon-dc-objs := vs_bridge.o vs_crtc.o vs_dc.o vs_drm.o vs_hwdb.o \
|
||||
vs_plane.o vs_primary_plane.o vs_cursor_plane.o
|
||||
|
||||
obj-$(CONFIG_DRM_VERISILICON_DC) += verisilicon-dc.o
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ struct vs_crtc *vs_crtc_init(struct drm_device *drm_dev, struct vs_dc *dc,
|
|||
unsigned int output)
|
||||
{
|
||||
struct vs_crtc *vcrtc;
|
||||
struct drm_plane *primary;
|
||||
struct drm_plane *primary, *cursor;
|
||||
int ret;
|
||||
|
||||
vcrtc = drmm_kzalloc(drm_dev, sizeof(*vcrtc), GFP_KERNEL);
|
||||
|
|
@ -175,9 +175,16 @@ struct vs_crtc *vs_crtc_init(struct drm_device *drm_dev, struct vs_dc *dc,
|
|||
return ERR_PTR(PTR_ERR(primary));
|
||||
}
|
||||
|
||||
/* Create our cursor plane */
|
||||
cursor = vs_cursor_plane_init(drm_dev, dc);
|
||||
if (IS_ERR(cursor)) {
|
||||
drm_err(drm_dev, "Couldn't create the cursor plane\n");
|
||||
return ERR_CAST(cursor);
|
||||
}
|
||||
|
||||
ret = drmm_crtc_init_with_planes(drm_dev, &vcrtc->base,
|
||||
primary,
|
||||
NULL,
|
||||
cursor,
|
||||
&vs_crtc_funcs,
|
||||
NULL);
|
||||
if (ret) {
|
||||
|
|
|
|||
272
drivers/gpu/drm/verisilicon/vs_cursor_plane.c
Normal file
272
drivers/gpu/drm/verisilicon/vs_cursor_plane.c
Normal file
|
|
@ -0,0 +1,272 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2026 Institute of Software, Chinese Academy of Sciences (ISCAS)
|
||||
*
|
||||
* Authors:
|
||||
* Icenowy Zheng <zhengxingda@iscas.ac.cn>
|
||||
*/
|
||||
|
||||
#include <linux/log2.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_gem_atomic_helper.h>
|
||||
#include <drm/drm_modeset_helper_vtables.h>
|
||||
#include <drm/drm_plane.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "vs_crtc.h"
|
||||
#include "vs_plane.h"
|
||||
#include "vs_dc.h"
|
||||
#include "vs_hwdb.h"
|
||||
#include "vs_cursor_plane_regs.h"
|
||||
|
||||
#define VSDC_MIN_CURSOR_SIZE 32
|
||||
#define VSDC_MAX_CURSOR_SIZE 256
|
||||
|
||||
#define VSDC_CURSOR_LOCATION_MAX_POSITIVE BIT_MASK(15)
|
||||
#define VSDC_CURSOR_LOCATION_MAX_NEGATIVE BIT_MASK(5)
|
||||
|
||||
static bool vs_cursor_plane_check_coord(int32_t coord)
|
||||
{
|
||||
if (coord >= 0)
|
||||
return coord <= VSDC_CURSOR_LOCATION_MAX_POSITIVE;
|
||||
else
|
||||
return (-coord) <= VSDC_CURSOR_LOCATION_MAX_NEGATIVE;
|
||||
}
|
||||
|
||||
static int vs_cursor_plane_atomic_check(struct drm_plane *plane,
|
||||
struct drm_atomic_commit *state)
|
||||
{
|
||||
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
|
||||
plane);
|
||||
struct drm_crtc *crtc = new_plane_state->crtc;
|
||||
struct drm_framebuffer *fb = new_plane_state->fb;
|
||||
struct drm_crtc_state *crtc_state = NULL;
|
||||
struct vs_crtc *vcrtc;
|
||||
struct vs_dc *dc;
|
||||
int ret;
|
||||
|
||||
if (crtc)
|
||||
crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(new_plane_state,
|
||||
crtc_state,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
true, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!new_plane_state->visible)
|
||||
return 0; /* Skip validity check */
|
||||
|
||||
vcrtc = drm_crtc_to_vs_crtc(crtc);
|
||||
dc = vcrtc->dc;
|
||||
|
||||
/* Only certain PoT square sizes is supported. */
|
||||
if (!is_power_of_2(new_plane_state->crtc_w) ||
|
||||
new_plane_state->crtc_w < VSDC_MIN_CURSOR_SIZE ||
|
||||
new_plane_state->crtc_w > dc->identity.max_cursor_size)
|
||||
return -EINVAL;
|
||||
|
||||
if (new_plane_state->crtc_w != new_plane_state->crtc_h)
|
||||
return -EINVAL;
|
||||
|
||||
/* Check if the cursor is inside the register fields' range */
|
||||
if (!vs_cursor_plane_check_coord(new_plane_state->crtc_x) ||
|
||||
!vs_cursor_plane_check_coord(new_plane_state->crtc_y))
|
||||
return -EINVAL;
|
||||
|
||||
/* Extra line padding isn't supported */
|
||||
if (fb->pitches[0] !=
|
||||
drm_format_info_min_pitch(fb->format, 0, new_plane_state->crtc_w))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vs_cursor_plane_commit(struct vs_dc *dc, unsigned int output)
|
||||
{
|
||||
regmap_set_bits(dc->regs, VSDC_CURSOR_CONFIG(output),
|
||||
VSDC_CURSOR_CONFIG_COMMIT |
|
||||
VSDC_CURSOR_CONFIG_IMG_UPDATE);
|
||||
}
|
||||
|
||||
static void vs_cursor_plane_atomic_enable(struct drm_plane *plane,
|
||||
struct drm_atomic_commit *atomic_state)
|
||||
{
|
||||
struct drm_plane_state *state = drm_atomic_get_new_plane_state(atomic_state,
|
||||
plane);
|
||||
struct drm_crtc *crtc = state->crtc;
|
||||
struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
|
||||
unsigned int output = vcrtc->id;
|
||||
struct vs_dc *dc = vcrtc->dc;
|
||||
|
||||
regmap_update_bits(dc->regs, VSDC_CURSOR_CONFIG(output),
|
||||
VSDC_CURSOR_CONFIG_FMT_MASK,
|
||||
VSDC_CURSOR_CONFIG_FMT_ARGB8888);
|
||||
|
||||
vs_cursor_plane_commit(dc, output);
|
||||
}
|
||||
|
||||
static void vs_cursor_plane_atomic_disable(struct drm_plane *plane,
|
||||
struct drm_atomic_commit *atomic_state)
|
||||
{
|
||||
struct drm_plane_state *state = drm_atomic_get_old_plane_state(atomic_state,
|
||||
plane);
|
||||
struct drm_crtc *crtc = state->crtc;
|
||||
struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
|
||||
unsigned int output = vcrtc->id;
|
||||
struct vs_dc *dc = vcrtc->dc;
|
||||
|
||||
regmap_update_bits(dc->regs, VSDC_CURSOR_CONFIG(output),
|
||||
VSDC_CURSOR_CONFIG_FMT_MASK,
|
||||
VSDC_CURSOR_CONFIG_FMT_OFF);
|
||||
|
||||
vs_cursor_plane_commit(dc, output);
|
||||
}
|
||||
|
||||
static void vs_cursor_plane_atomic_update(struct drm_plane *plane,
|
||||
struct drm_atomic_commit *atomic_state)
|
||||
{
|
||||
struct drm_plane_state *state = drm_atomic_get_new_plane_state(atomic_state,
|
||||
plane);
|
||||
struct drm_framebuffer *fb = state->fb;
|
||||
struct drm_crtc *crtc = state->crtc;
|
||||
struct vs_dc *dc;
|
||||
struct vs_crtc *vcrtc;
|
||||
unsigned int output;
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
if (!state->visible) {
|
||||
vs_cursor_plane_atomic_disable(plane, atomic_state);
|
||||
return;
|
||||
}
|
||||
|
||||
vcrtc = drm_crtc_to_vs_crtc(crtc);
|
||||
output = vcrtc->id;
|
||||
dc = vcrtc->dc;
|
||||
|
||||
/* Other sizes should be rejected by atomic_check */
|
||||
switch (state->crtc_w) {
|
||||
case 32:
|
||||
regmap_update_bits(dc->regs, VSDC_CURSOR_CONFIG(output),
|
||||
VSDC_CURSOR_CONFIG_SIZE_MASK,
|
||||
VSDC_CURSOR_CONFIG_SIZE_32);
|
||||
break;
|
||||
case 64:
|
||||
regmap_update_bits(dc->regs, VSDC_CURSOR_CONFIG(output),
|
||||
VSDC_CURSOR_CONFIG_SIZE_MASK,
|
||||
VSDC_CURSOR_CONFIG_SIZE_64);
|
||||
break;
|
||||
case 128:
|
||||
regmap_update_bits(dc->regs, VSDC_CURSOR_CONFIG(output),
|
||||
VSDC_CURSOR_CONFIG_SIZE_MASK,
|
||||
VSDC_CURSOR_CONFIG_SIZE_128);
|
||||
break;
|
||||
case 256:
|
||||
regmap_update_bits(dc->regs, VSDC_CURSOR_CONFIG(output),
|
||||
VSDC_CURSOR_CONFIG_SIZE_MASK,
|
||||
VSDC_CURSOR_CONFIG_SIZE_256);
|
||||
break;
|
||||
}
|
||||
|
||||
dma_addr = vs_fb_get_dma_addr(fb, &state->src);
|
||||
|
||||
regmap_write(dc->regs, VSDC_CURSOR_ADDRESS(output),
|
||||
lower_32_bits(dma_addr));
|
||||
|
||||
/*
|
||||
* The X_OFF and Y_OFF fields define which point does the LOCATION
|
||||
* register represent in the cursor image, and LOCATION register
|
||||
* values are unsigned. To for positive left-top coordinates the
|
||||
* offset is set to 0 and the location is set to the coordinate, for
|
||||
* negative coordinates the location is set to 0 and the offset
|
||||
* is set to the opposite number of the coordinate to offset the
|
||||
* cursor image partly off-screen.
|
||||
*/
|
||||
if (state->crtc_x >= 0) {
|
||||
regmap_update_bits(dc->regs, VSDC_CURSOR_CONFIG(output),
|
||||
VSDC_CURSOR_CONFIG_X_OFF_MASK, 0);
|
||||
regmap_update_bits(dc->regs, VSDC_CURSOR_LOCATION(output),
|
||||
VSDC_CURSOR_LOCATION_X_MASK,
|
||||
VSDC_CURSOR_LOCATION_X(state->crtc_x));
|
||||
} else {
|
||||
regmap_update_bits(dc->regs, VSDC_CURSOR_CONFIG(output),
|
||||
VSDC_CURSOR_CONFIG_X_OFF_MASK,
|
||||
-state->crtc_x);
|
||||
regmap_update_bits(dc->regs, VSDC_CURSOR_LOCATION(output),
|
||||
VSDC_CURSOR_LOCATION_X_MASK, 0);
|
||||
}
|
||||
|
||||
if (state->crtc_y >= 0) {
|
||||
regmap_update_bits(dc->regs, VSDC_CURSOR_CONFIG(output),
|
||||
VSDC_CURSOR_CONFIG_Y_OFF_MASK, 0);
|
||||
regmap_update_bits(dc->regs, VSDC_CURSOR_LOCATION(output),
|
||||
VSDC_CURSOR_LOCATION_Y_MASK,
|
||||
VSDC_CURSOR_LOCATION_Y(state->crtc_y));
|
||||
} else {
|
||||
regmap_update_bits(dc->regs, VSDC_CURSOR_CONFIG(output),
|
||||
VSDC_CURSOR_CONFIG_Y_OFF_MASK,
|
||||
-state->crtc_y);
|
||||
regmap_update_bits(dc->regs, VSDC_CURSOR_LOCATION(output),
|
||||
VSDC_CURSOR_LOCATION_Y_MASK, 0);
|
||||
}
|
||||
|
||||
vs_cursor_plane_commit(dc, output);
|
||||
}
|
||||
|
||||
static const struct drm_plane_helper_funcs vs_cursor_plane_helper_funcs = {
|
||||
.atomic_check = vs_cursor_plane_atomic_check,
|
||||
.atomic_update = vs_cursor_plane_atomic_update,
|
||||
.atomic_enable = vs_cursor_plane_atomic_enable,
|
||||
.atomic_disable = vs_cursor_plane_atomic_disable,
|
||||
};
|
||||
|
||||
static const struct drm_plane_funcs vs_cursor_plane_funcs = {
|
||||
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
|
||||
.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
|
||||
.disable_plane = drm_atomic_helper_disable_plane,
|
||||
.reset = drm_atomic_helper_plane_reset,
|
||||
.update_plane = drm_atomic_helper_update_plane,
|
||||
};
|
||||
|
||||
static const u32 vs_cursor_plane_formats[] = {
|
||||
DRM_FORMAT_ARGB8888,
|
||||
};
|
||||
|
||||
static const u64 vs_cursor_plane_modifiers[] = {
|
||||
DRM_FORMAT_MOD_LINEAR,
|
||||
DRM_FORMAT_MOD_INVALID, /* sentinel */
|
||||
};
|
||||
|
||||
struct drm_plane *vs_cursor_plane_init(struct drm_device *drm_dev,
|
||||
struct vs_dc *dc)
|
||||
{
|
||||
int32_t max_cursor_size = dc->identity.max_cursor_size;
|
||||
struct drm_plane *plane;
|
||||
|
||||
if (drm_WARN_ON_ONCE(drm_dev, max_cursor_size < VSDC_MIN_CURSOR_SIZE ||
|
||||
max_cursor_size > VSDC_MAX_CURSOR_SIZE))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
plane = drmm_universal_plane_alloc(drm_dev, struct drm_plane, dev, 0,
|
||||
&vs_cursor_plane_funcs,
|
||||
vs_cursor_plane_formats,
|
||||
ARRAY_SIZE(vs_cursor_plane_formats),
|
||||
vs_cursor_plane_modifiers,
|
||||
DRM_PLANE_TYPE_CURSOR,
|
||||
NULL);
|
||||
|
||||
if (IS_ERR(plane))
|
||||
return plane;
|
||||
|
||||
drm_plane_helper_add(plane, &vs_cursor_plane_helper_funcs);
|
||||
|
||||
return plane;
|
||||
}
|
||||
44
drivers/gpu/drm/verisilicon/vs_cursor_plane_regs.h
Normal file
44
drivers/gpu/drm/verisilicon/vs_cursor_plane_regs.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2025 Icenowy Zheng <uwu@icenowy.me>
|
||||
*
|
||||
* Based on vs_dc_hw.h, which is:
|
||||
* Copyright (C) 2023 VeriSilicon Holdings Co., Ltd.
|
||||
*/
|
||||
|
||||
#ifndef _VS_CURSOR_PLANE_REGS_H_
|
||||
#define _VS_CURSOR_PLANE_REGS_H_
|
||||
|
||||
#include <linux/bits.h>
|
||||
|
||||
#define VSDC_CURSOR_CONFIG(n) (0x1468 + 0x1080 * (n))
|
||||
#define VSDC_CURSOR_CONFIG_FMT_MASK GENMASK(1, 0)
|
||||
#define VSDC_CURSOR_CONFIG_FMT_ARGB8888 (0x2 << 0)
|
||||
#define VSDC_CURSOR_CONFIG_FMT_OFF (0x0 << 0)
|
||||
#define VSDC_CURSOR_CONFIG_IMG_UPDATE BIT(2)
|
||||
#define VSDC_CURSOR_CONFIG_COMMIT BIT(3)
|
||||
#define VSDC_CURSOR_CONFIG_SIZE_MASK GENMASK(7, 5)
|
||||
#define VSDC_CURSOR_CONFIG_SIZE_32 (0x0 << 5)
|
||||
#define VSDC_CURSOR_CONFIG_SIZE_64 (0x1 << 5)
|
||||
#define VSDC_CURSOR_CONFIG_SIZE_128 (0x2 << 5)
|
||||
#define VSDC_CURSOR_CONFIG_SIZE_256 (0x3 << 5)
|
||||
#define VSDC_CURSOR_CONFIG_Y_OFF_MASK GENMASK(12, 8)
|
||||
#define VSDC_CURSOR_CONFIG_Y_OFF(v) ((v) << 8)
|
||||
#define VSDC_CURSOR_CONFIG_X_OFF_MASK GENMASK(20, 16)
|
||||
#define VSDC_CURSOR_CONFIG_X_OFF(v) ((v) << 16)
|
||||
|
||||
#define VSDC_CURSOR_ADDRESS(n) (0x146C + 0x1080 * (n))
|
||||
|
||||
#define VSDC_CURSOR_LOCATION(n) (0x1470 + 0x1080 * (n))
|
||||
#define VSDC_CURSOR_LOCATION_X_MASK GENMASK(14, 0)
|
||||
#define VSDC_CURSOR_LOCATION_X(v) ((v) << 0)
|
||||
#define VSDC_CURSOR_LOCATION_Y_MASK GENMASK(30, 16)
|
||||
#define VSDC_CURSOR_LOCATION_Y(v) ((v) << 16)
|
||||
|
||||
#define VSDC_CURSOR_BACKGROUND(n) (0x1474 + 0x1080 * (n))
|
||||
#define VSDC_CURSOR_BACKGRUOND_DEFAULT 0x00FFFFFF
|
||||
|
||||
#define VSDC_CURSOR_FOREGROUND(n) (0x1478 + 0x1080 * (n))
|
||||
#define VSDC_CURSOR_FOREGRUOND_DEFAULT 0x00AAAAAA
|
||||
|
||||
#endif /* _VS_CURSOR_PLANE_REGS_H_ */
|
||||
|
|
@ -95,6 +95,7 @@ static struct vs_chip_identity vs_chip_identities[] = {
|
|||
.customer_id = ~0U,
|
||||
|
||||
.display_count = 2,
|
||||
.max_cursor_size = 64,
|
||||
.formats = &vs_formats_no_yuv444,
|
||||
},
|
||||
{
|
||||
|
|
@ -103,6 +104,7 @@ static struct vs_chip_identity vs_chip_identities[] = {
|
|||
.customer_id = 0x30B,
|
||||
|
||||
.display_count = 2,
|
||||
.max_cursor_size = 64,
|
||||
.formats = &vs_formats_no_yuv444,
|
||||
},
|
||||
{
|
||||
|
|
@ -111,6 +113,7 @@ static struct vs_chip_identity vs_chip_identities[] = {
|
|||
.customer_id = 0x310,
|
||||
|
||||
.display_count = 2,
|
||||
.max_cursor_size = 64,
|
||||
.formats = &vs_formats_with_yuv444,
|
||||
},
|
||||
{
|
||||
|
|
@ -119,6 +122,7 @@ static struct vs_chip_identity vs_chip_identities[] = {
|
|||
.customer_id = 0x311,
|
||||
|
||||
.display_count = 2,
|
||||
.max_cursor_size = 64,
|
||||
.formats = &vs_formats_no_yuv444,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@ struct vs_chip_identity {
|
|||
u32 customer_id;
|
||||
|
||||
u32 display_count;
|
||||
/*
|
||||
* The hardware only supports square cursor planes, so this field
|
||||
* is both the maximum width and height in pixels.
|
||||
*/
|
||||
int32_t max_cursor_size;
|
||||
const struct vs_formats *formats;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -84,5 +84,6 @@ void vs_plane_destroy_state(struct drm_plane *plane,
|
|||
void vs_plane_reset(struct drm_plane *plane);
|
||||
|
||||
struct drm_plane *vs_primary_plane_init(struct drm_device *dev, struct vs_dc *dc);
|
||||
struct drm_plane *vs_cursor_plane_init(struct drm_device *dev, struct vs_dc *dc);
|
||||
|
||||
#endif /* _VS_PLANE_H_ */
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ int xe_validation_ctx_init(struct xe_validation_ctx *ctx, struct xe_validation_d
|
|||
|
||||
#ifdef CONFIG_DEBUG_WW_MUTEX_SLOWPATH
|
||||
/*
|
||||
* This abuses both drm_exec and ww_mutex internals and should be
|
||||
* This abuses ww_mutex internals and should be
|
||||
* replaced by checking for -EDEADLK when we can make TTM
|
||||
* stop converting -EDEADLK to -ENOMEM.
|
||||
* An alternative is to not have exhaustive eviction with
|
||||
|
|
@ -164,7 +164,7 @@ int xe_validation_ctx_init(struct xe_validation_ctx *ctx, struct xe_validation_d
|
|||
*/
|
||||
static bool xe_validation_contention_injected(struct drm_exec *exec)
|
||||
{
|
||||
return !!exec->ticket.contending_lock;
|
||||
return !!drm_exec_ticket(exec)->contending_lock;
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ bool xe_validation_should_retry(struct xe_validation_ctx *ctx, int *ret);
|
|||
#define xe_validation_retry_on_oom(_ctx, _ret) \
|
||||
do { \
|
||||
if (xe_validation_should_retry(_ctx, _ret)) \
|
||||
goto *__drm_exec_retry_ptr; \
|
||||
drm_exec_retry((_ctx)->exec); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -373,7 +373,6 @@ int xe_vm_validate_rebind(struct xe_vm *vm, struct drm_exec *exec,
|
|||
unsigned int num_fences)
|
||||
{
|
||||
struct drm_gem_object *obj;
|
||||
unsigned long index;
|
||||
int ret;
|
||||
|
||||
do {
|
||||
|
|
@ -386,7 +385,7 @@ int xe_vm_validate_rebind(struct xe_vm *vm, struct drm_exec *exec,
|
|||
return ret;
|
||||
} while (!list_empty(&vm->gpuvm.evict.list));
|
||||
|
||||
drm_exec_for_each_locked_object(exec, index, obj) {
|
||||
drm_exec_for_each_locked_object(exec, obj) {
|
||||
ret = dma_resv_reserve_fences(obj->resv, num_fences);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ int host1x_device_init(struct host1x_device *device)
|
|||
|
||||
teardown:
|
||||
list_for_each_entry_continue_reverse(client, &device->clients, list)
|
||||
if (client->ops->exit)
|
||||
if (client->ops && client->ops->exit)
|
||||
client->ops->exit(client);
|
||||
|
||||
/* reset client to end of list for late teardown */
|
||||
|
|
@ -229,7 +229,7 @@ int host1x_device_init(struct host1x_device *device)
|
|||
|
||||
teardown_late:
|
||||
list_for_each_entry_continue_reverse(client, &device->clients, list)
|
||||
if (client->ops->late_exit)
|
||||
if (client->ops && client->ops->late_exit)
|
||||
client->ops->late_exit(client);
|
||||
|
||||
mutex_unlock(&device->clients_lock);
|
||||
|
|
@ -485,7 +485,7 @@ static int host1x_device_add(struct host1x *host1x,
|
|||
|
||||
err = host1x_device_parse_dt(device, driver);
|
||||
if (err < 0) {
|
||||
kfree(device);
|
||||
put_device(&device->dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -887,6 +887,20 @@ int host1x_client_resume(struct host1x_client *client)
|
|||
}
|
||||
EXPORT_SYMBOL(host1x_client_resume);
|
||||
|
||||
/**
|
||||
* host1x_bo_pin() - Create a DMA mapping for the buffer object
|
||||
* @dev: Device onto which DMA map to
|
||||
* @bo: Buffer object to map
|
||||
* @dir: DMA direction
|
||||
* @cache: Cache in which to store mapping, or NULL
|
||||
*
|
||||
* Creates a DMA mapping pointing to @bo for @dev. The refcount of @bo is incremented
|
||||
* until host1x_bo_unpin is called.
|
||||
*
|
||||
* If @cache is specified, the mapping is also stored in the cache and not released
|
||||
* until @bo is freed (refcount drops to zero). This improves performance when a buffer
|
||||
* is pinned and unpinned frequently as in the case of display use.
|
||||
*/
|
||||
struct host1x_bo_mapping *host1x_bo_pin(struct device *dev, struct host1x_bo *bo,
|
||||
enum dma_data_direction dir,
|
||||
struct host1x_bo_cache *cache)
|
||||
|
|
@ -899,6 +913,7 @@ struct host1x_bo_mapping *host1x_bo_pin(struct device *dev, struct host1x_bo *bo
|
|||
list_for_each_entry(mapping, &cache->mappings, entry) {
|
||||
if (mapping->bo == bo && mapping->direction == dir) {
|
||||
kref_get(&mapping->ref);
|
||||
host1x_bo_get(bo);
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
|
|
@ -908,6 +923,8 @@ struct host1x_bo_mapping *host1x_bo_pin(struct device *dev, struct host1x_bo *bo
|
|||
if (IS_ERR(mapping))
|
||||
goto unlock;
|
||||
|
||||
host1x_bo_get(bo);
|
||||
|
||||
spin_lock(&mapping->bo->lock);
|
||||
list_add_tail(&mapping->list, &bo->mappings);
|
||||
spin_unlock(&mapping->bo->lock);
|
||||
|
|
@ -918,7 +935,12 @@ struct host1x_bo_mapping *host1x_bo_pin(struct device *dev, struct host1x_bo *bo
|
|||
|
||||
list_add_tail(&mapping->entry, &cache->mappings);
|
||||
|
||||
/* bump reference count to track the copy in the cache */
|
||||
/*
|
||||
* Bump the mapping reference count to track the mapping in the cache,
|
||||
* but do not bump the BO's refcount. This allows the BO to still get freed,
|
||||
* triggering the release of the cache mapping through
|
||||
* host1x_bo_clear_cached_mappings.
|
||||
*/
|
||||
kref_get(&mapping->ref);
|
||||
}
|
||||
|
||||
|
|
@ -948,9 +970,17 @@ static void __host1x_bo_unpin(struct kref *ref)
|
|||
mapping->bo->ops->unpin(mapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* host1x_bo_unpin() - Release an established DMA mapping of a buffer object
|
||||
* @mapping: Mapping to release
|
||||
*
|
||||
* Unmaps the given @mapping, unless it is cached. Decreases the refcount on
|
||||
* the underlying buffer object.
|
||||
*/
|
||||
void host1x_bo_unpin(struct host1x_bo_mapping *mapping)
|
||||
{
|
||||
struct host1x_bo_cache *cache = mapping->cache;
|
||||
struct host1x_bo *bo = mapping->bo;
|
||||
|
||||
if (cache)
|
||||
mutex_lock(&cache->lock);
|
||||
|
|
@ -959,5 +989,33 @@ void host1x_bo_unpin(struct host1x_bo_mapping *mapping)
|
|||
|
||||
if (cache)
|
||||
mutex_unlock(&cache->lock);
|
||||
|
||||
host1x_bo_put(bo);
|
||||
}
|
||||
EXPORT_SYMBOL(host1x_bo_unpin);
|
||||
|
||||
/**
|
||||
* host1x_bo_clear_cached_mappings() - Remove all cached mappings pointing at a bo
|
||||
* @bo: Buffer object to release mappings of
|
||||
*
|
||||
* Drops references to any mappings pointing to @bo left in any caches. This must
|
||||
* be called by any host1x_bo implementers that may be pinned with caching enabled
|
||||
* before freeing the bo.
|
||||
*/
|
||||
void host1x_bo_clear_cached_mappings(struct host1x_bo *bo)
|
||||
{
|
||||
struct host1x_bo_mapping *mapping, *tmp;
|
||||
struct host1x_bo_cache *cache;
|
||||
|
||||
list_for_each_entry_safe(mapping, tmp, &bo->mappings, list) {
|
||||
cache = mapping->cache;
|
||||
if (WARN_ON(!cache))
|
||||
continue;
|
||||
|
||||
mutex_lock(&mapping->cache->lock);
|
||||
WARN_ON(kref_read(&mapping->ref) != 1);
|
||||
__host1x_bo_unpin(&mapping->ref);
|
||||
mutex_unlock(&mapping->cache->lock);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(host1x_bo_clear_cached_mappings);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/host1x_context_bus.h>
|
||||
#include <linux/kref.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
|
|
|
|||
|
|
@ -12,8 +12,7 @@
|
|||
#include <linux/refcount.h>
|
||||
|
||||
struct host1x;
|
||||
|
||||
extern struct bus_type host1x_context_device_bus_type;
|
||||
struct host1x_memory_context;
|
||||
|
||||
struct host1x_memory_context_list {
|
||||
struct mutex lock;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/host1x_context_bus.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
const struct bus_type host1x_context_device_bus_type = {
|
||||
|
|
|
|||
|
|
@ -92,8 +92,12 @@ void host1x_intr_handle_interrupt(struct host1x *host, unsigned int id)
|
|||
host1x_fence_signal(fence);
|
||||
}
|
||||
|
||||
/* Re-enable interrupt if necessary */
|
||||
host1x_intr_update_hw_state(host, sp);
|
||||
/*
|
||||
* Re-enable interrupt if necessary. The ISR already disabled the interrupt,
|
||||
* so if no fences remain, no update is needed.
|
||||
*/
|
||||
if (!list_empty(&sp->fences.list))
|
||||
host1x_intr_update_hw_state(host, sp);
|
||||
|
||||
spin_unlock(&sp->fences.lock);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -235,6 +235,8 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
|
|||
}
|
||||
|
||||
if (host->domain) {
|
||||
ssize_t map_err;
|
||||
|
||||
for_each_sgtable_sg(map->sgt, sg, j)
|
||||
gather_size += sg->length;
|
||||
|
||||
|
|
@ -248,11 +250,11 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
|
|||
goto put;
|
||||
}
|
||||
|
||||
err = iommu_map_sgtable(host->domain, iova_dma_addr(&host->iova, alloc),
|
||||
map->sgt, IOMMU_READ);
|
||||
if (err == 0) {
|
||||
map_err = iommu_map_sgtable(host->domain, iova_dma_addr(&host->iova, alloc),
|
||||
map->sgt, IOMMU_READ);
|
||||
if (map_err < 0) {
|
||||
__free_iova(&host->iova, alloc);
|
||||
err = -EINVAL;
|
||||
err = map_err;
|
||||
goto put;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -114,8 +114,10 @@ struct tegra_mipi_device *tegra_mipi_request(struct device *device,
|
|||
if (err < 0)
|
||||
return ERR_PTR(err);
|
||||
|
||||
if (provider.np != args.np)
|
||||
return ERR_PTR(-ENODEV);
|
||||
if (provider.np != args.np) {
|
||||
err = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mipidev = kzalloc_obj(*mipidev);
|
||||
if (!mipidev) {
|
||||
|
|
|
|||
|
|
@ -222,11 +222,12 @@ int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout,
|
|||
{
|
||||
struct dma_fence *fence;
|
||||
long wait_err;
|
||||
u32 curr;
|
||||
|
||||
host1x_hw_syncpt_load(sp->host, sp);
|
||||
curr = host1x_syncpt_load(sp);
|
||||
|
||||
if (value)
|
||||
*value = host1x_syncpt_load(sp);
|
||||
*value = curr;
|
||||
|
||||
if (host1x_syncpt_is_expired(sp, thresh))
|
||||
return 0;
|
||||
|
|
@ -245,21 +246,25 @@ int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout,
|
|||
host1x_fence_cancel(fence);
|
||||
dma_fence_put(fence);
|
||||
|
||||
if (value)
|
||||
*value = host1x_syncpt_load(sp);
|
||||
|
||||
/*
|
||||
* Don't rely on dma_fence_wait_timeout return value,
|
||||
* since it returns zero both on timeout and if the
|
||||
* wait completed with 0 jiffies left.
|
||||
*/
|
||||
host1x_hw_syncpt_load(sp->host, sp);
|
||||
if (wait_err == 0 && !host1x_syncpt_is_expired(sp, thresh))
|
||||
if (wait_err == 0 && !host1x_syncpt_is_expired(sp, thresh)) {
|
||||
if (value)
|
||||
*value = host1x_syncpt_load(sp);
|
||||
|
||||
return -EAGAIN;
|
||||
else if (wait_err < 0)
|
||||
} else if (wait_err < 0) {
|
||||
return wait_err;
|
||||
else
|
||||
} else {
|
||||
/* Success, read the value cached by ISR */
|
||||
if (value)
|
||||
*value = host1x_syncpt_read_min(sp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(host1x_syncpt_wait);
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,12 @@
|
|||
#define DRM_EXEC_INTERRUPTIBLE_WAIT BIT(0)
|
||||
#define DRM_EXEC_IGNORE_DUPLICATES BIT(1)
|
||||
|
||||
/*
|
||||
* Dummy value used to initially enter the retry loop.
|
||||
* internal use only.
|
||||
*/
|
||||
#define DRM_EXEC_DUMMY ((void *)~0)
|
||||
|
||||
struct drm_gem_object;
|
||||
|
||||
/**
|
||||
|
|
@ -65,31 +71,46 @@ drm_exec_obj(struct drm_exec *exec, unsigned long index)
|
|||
return index < exec->num_objects ? exec->objects[index] : NULL;
|
||||
}
|
||||
|
||||
/* Helper for drm_exec_for_each_locked_object(). Internal use only. */
|
||||
#define __drm_exec_for_each_locked_object(exec, obj, __index) \
|
||||
for (unsigned long __index = 0; ((obj) = drm_exec_obj(exec, __index)); ++__index)
|
||||
/**
|
||||
* drm_exec_for_each_locked_object - iterate over all the locked objects
|
||||
* @exec: drm_exec object
|
||||
* @index: unsigned long index for the iteration
|
||||
* @obj: the current GEM object
|
||||
*
|
||||
* Iterate over all the locked GEM objects inside the drm_exec object.
|
||||
*/
|
||||
#define drm_exec_for_each_locked_object(exec, index, obj) \
|
||||
for ((index) = 0; ((obj) = drm_exec_obj(exec, index)); ++(index))
|
||||
#define drm_exec_for_each_locked_object(exec, obj) \
|
||||
__drm_exec_for_each_locked_object(exec, obj, __UNIQUE_ID(drm_exec))
|
||||
|
||||
/* Helper for drm_exec_for_each_locked_object_reverse(). Internal use only. */
|
||||
#define __drm_exec_for_each_locked_object_reverse(exec, obj, __index) \
|
||||
for (unsigned long __index = (exec)->num_objects - 1; \
|
||||
((obj) = drm_exec_obj(exec, __index)); --__index)
|
||||
/**
|
||||
* drm_exec_for_each_locked_object_reverse - iterate over all the locked
|
||||
* objects in reverse locking order
|
||||
* @exec: drm_exec object
|
||||
* @index: unsigned long index for the iteration
|
||||
* @obj: the current GEM object
|
||||
*
|
||||
* Iterate over all the locked GEM objects inside the drm_exec object in
|
||||
* reverse locking order. Note that @index may go below zero and wrap,
|
||||
* reverse locking order. Note that the internal index may wrap around,
|
||||
* but that will be caught by drm_exec_obj(), returning a NULL object.
|
||||
*/
|
||||
#define drm_exec_for_each_locked_object_reverse(exec, index, obj) \
|
||||
for ((index) = (exec)->num_objects - 1; \
|
||||
((obj) = drm_exec_obj(exec, index)); --(index))
|
||||
#define drm_exec_for_each_locked_object_reverse(exec, obj) \
|
||||
__drm_exec_for_each_locked_object_reverse(exec, obj, __UNIQUE_ID(drm_exec))
|
||||
|
||||
/*
|
||||
* Helper to drm_exec_until_all_locked(). Don't use directly.
|
||||
*
|
||||
* Since labels can't be defined local to the loop's body we use a jump pointer
|
||||
* to make sure that the retry is only used from within the loop's body.
|
||||
*/
|
||||
#define __drm_exec_until_all_locked(exec, _label) \
|
||||
_label: \
|
||||
for (void *const __maybe_unused __drm_exec_retry_ptr = &&_label; \
|
||||
drm_exec_cleanup(exec);)
|
||||
|
||||
/**
|
||||
* drm_exec_until_all_locked - loop until all GEM objects are locked
|
||||
|
|
@ -98,17 +119,9 @@ drm_exec_obj(struct drm_exec *exec, unsigned long index)
|
|||
* Core functionality of the drm_exec object. Loops until all GEM objects are
|
||||
* locked and no more contention exists. At the beginning of the loop it is
|
||||
* guaranteed that no GEM object is locked.
|
||||
*
|
||||
* Since labels can't be defined local to the loops body we use a jump pointer
|
||||
* to make sure that the retry is only used from within the loops body.
|
||||
*/
|
||||
#define drm_exec_until_all_locked(exec) \
|
||||
__PASTE(__drm_exec_, __LINE__): \
|
||||
for (void *__drm_exec_retry_ptr; ({ \
|
||||
__drm_exec_retry_ptr = &&__PASTE(__drm_exec_, __LINE__);\
|
||||
(void)__drm_exec_retry_ptr; \
|
||||
drm_exec_cleanup(exec); \
|
||||
});)
|
||||
__drm_exec_until_all_locked(exec, __UNIQUE_ID(drm_exec))
|
||||
|
||||
/**
|
||||
* drm_exec_retry_on_contention - restart the loop to grap all locks
|
||||
|
|
@ -135,6 +148,30 @@ static inline bool drm_exec_is_contended(struct drm_exec *exec)
|
|||
return !!exec->contended;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_exec_retry() - Unconditionally restart the loop to grab all locks.
|
||||
* @exec: drm_exec object
|
||||
*
|
||||
* Unconditionally retry the loop to lock all objects. For consistency,
|
||||
* the exec object needs to be newly initialized.
|
||||
*/
|
||||
#define drm_exec_retry(_exec) \
|
||||
do { \
|
||||
WARN_ON((_exec)->contended != DRM_EXEC_DUMMY); \
|
||||
goto *__drm_exec_retry_ptr; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* drm_exec_ticket - return the ww_acquire_ctx for this exec context
|
||||
* @exec: drm_exec object
|
||||
*
|
||||
* Return: Pointer to the ww_acquire_ctx embedded in @exec.
|
||||
*/
|
||||
static inline struct ww_acquire_ctx *drm_exec_ticket(struct drm_exec *exec)
|
||||
{
|
||||
return &exec->ticket;
|
||||
}
|
||||
|
||||
void drm_exec_init(struct drm_exec *exec, u32 flags, unsigned nr);
|
||||
void drm_exec_fini(struct drm_exec *exec);
|
||||
bool drm_exec_cleanup(struct drm_exec *exec);
|
||||
|
|
|
|||
|
|
@ -143,6 +143,12 @@ static inline struct host1x_bo_mapping *to_host1x_bo_mapping(struct kref *ref)
|
|||
return container_of(ref, struct host1x_bo_mapping, ref);
|
||||
}
|
||||
|
||||
/**
|
||||
* struct host1x_bo_ops - operations implemented by a host1x_bo provider
|
||||
*
|
||||
* @pin: create a DMA mapping. Implementation must not touch the bo's refcount.
|
||||
* @unpin: destroy a DMA mapping. Implementation must not touch the bo's refcount.
|
||||
*/
|
||||
struct host1x_bo_ops {
|
||||
struct host1x_bo *(*get)(struct host1x_bo *bo);
|
||||
void (*put)(struct host1x_bo *bo);
|
||||
|
|
@ -181,6 +187,7 @@ struct host1x_bo_mapping *host1x_bo_pin(struct device *dev, struct host1x_bo *bo
|
|||
enum dma_data_direction dir,
|
||||
struct host1x_bo_cache *cache);
|
||||
void host1x_bo_unpin(struct host1x_bo_mapping *map);
|
||||
void host1x_bo_clear_cached_mappings(struct host1x_bo *bo);
|
||||
|
||||
static inline void *host1x_bo_mmap(struct host1x_bo *bo)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,9 +21,11 @@ struct host1x_bo;
|
|||
DECLARE_EVENT_CLASS(host1x,
|
||||
TP_PROTO(const char *name),
|
||||
TP_ARGS(name),
|
||||
TP_STRUCT__entry(__field(const char *, name)),
|
||||
TP_fast_assign(__entry->name = name;),
|
||||
TP_printk("name=%s", __entry->name)
|
||||
TP_STRUCT__entry(__string(name, name)),
|
||||
TP_fast_assign(
|
||||
__assign_str(name);
|
||||
),
|
||||
TP_printk("name=%s", __get_str(name))
|
||||
);
|
||||
|
||||
DEFINE_EVENT(host1x, host1x_channel_open,
|
||||
|
|
@ -52,19 +54,19 @@ TRACE_EVENT(host1x_cdma_push,
|
|||
TP_ARGS(name, op1, op2),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(const char *, name)
|
||||
__string(name, name)
|
||||
__field(u32, op1)
|
||||
__field(u32, op2)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->name = name;
|
||||
__assign_str(name);
|
||||
__entry->op1 = op1;
|
||||
__entry->op2 = op2;
|
||||
),
|
||||
|
||||
TP_printk("name=%s, op1=%08x, op2=%08x",
|
||||
__entry->name, __entry->op1, __entry->op2)
|
||||
__get_str(name), __entry->op1, __entry->op2)
|
||||
);
|
||||
|
||||
TRACE_EVENT(host1x_cdma_push_wide,
|
||||
|
|
@ -73,7 +75,7 @@ TRACE_EVENT(host1x_cdma_push_wide,
|
|||
TP_ARGS(name, op1, op2, op3, op4),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(const char *, name)
|
||||
__string(name, name)
|
||||
__field(u32, op1)
|
||||
__field(u32, op2)
|
||||
__field(u32, op3)
|
||||
|
|
@ -81,7 +83,7 @@ TRACE_EVENT(host1x_cdma_push_wide,
|
|||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->name = name;
|
||||
__assign_str(name);
|
||||
__entry->op1 = op1;
|
||||
__entry->op2 = op2;
|
||||
__entry->op3 = op3;
|
||||
|
|
@ -89,7 +91,7 @@ TRACE_EVENT(host1x_cdma_push_wide,
|
|||
),
|
||||
|
||||
TP_printk("name=%s, op1=%08x, op2=%08x, op3=%08x op4=%08x",
|
||||
__entry->name, __entry->op1, __entry->op2, __entry->op3,
|
||||
__get_str(name), __entry->op1, __entry->op2, __entry->op3,
|
||||
__entry->op4)
|
||||
);
|
||||
|
||||
|
|
@ -100,7 +102,7 @@ TRACE_EVENT(host1x_cdma_push_gather,
|
|||
TP_ARGS(name, bo, words, offset, cmdbuf),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(const char *, name)
|
||||
__string(name, name)
|
||||
__field(struct host1x_bo *, bo)
|
||||
__field(u32, words)
|
||||
__field(u32, offset)
|
||||
|
|
@ -114,14 +116,14 @@ TRACE_EVENT(host1x_cdma_push_gather,
|
|||
words * sizeof(u32));
|
||||
}
|
||||
__entry->cmdbuf = cmdbuf;
|
||||
__entry->name = name;
|
||||
__assign_str(name);
|
||||
__entry->bo = bo;
|
||||
__entry->words = words;
|
||||
__entry->offset = offset;
|
||||
),
|
||||
|
||||
TP_printk("name=%s, bo=%p, words=%u, offset=%d, contents=[%s]",
|
||||
__entry->name, __entry->bo,
|
||||
__get_str(name), __entry->bo,
|
||||
__entry->words, __entry->offset,
|
||||
__print_hex(__get_dynamic_array(cmdbuf),
|
||||
__entry->cmdbuf ? __entry->words * 4 : 0))
|
||||
|
|
@ -134,7 +136,7 @@ TRACE_EVENT(host1x_channel_submit,
|
|||
TP_ARGS(name, cmdbufs, relocs, syncpt_id, syncpt_incrs),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(const char *, name)
|
||||
__string(name, name)
|
||||
__field(u32, cmdbufs)
|
||||
__field(u32, relocs)
|
||||
__field(u32, syncpt_id)
|
||||
|
|
@ -142,7 +144,7 @@ TRACE_EVENT(host1x_channel_submit,
|
|||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->name = name;
|
||||
__assign_str(name);
|
||||
__entry->cmdbufs = cmdbufs;
|
||||
__entry->relocs = relocs;
|
||||
__entry->syncpt_id = syncpt_id;
|
||||
|
|
@ -151,7 +153,7 @@ TRACE_EVENT(host1x_channel_submit,
|
|||
|
||||
TP_printk("name=%s, cmdbufs=%u, relocs=%u, syncpt_id=%u, "
|
||||
"syncpt_incrs=%u",
|
||||
__entry->name, __entry->cmdbufs, __entry->relocs,
|
||||
__get_str(name), __entry->cmdbufs, __entry->relocs,
|
||||
__entry->syncpt_id, __entry->syncpt_incrs)
|
||||
);
|
||||
|
||||
|
|
@ -161,19 +163,19 @@ TRACE_EVENT(host1x_channel_submitted,
|
|||
TP_ARGS(name, syncpt_base, syncpt_max),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(const char *, name)
|
||||
__string(name, name)
|
||||
__field(u32, syncpt_base)
|
||||
__field(u32, syncpt_max)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->name = name;
|
||||
__assign_str(name);
|
||||
__entry->syncpt_base = syncpt_base;
|
||||
__entry->syncpt_max = syncpt_max;
|
||||
),
|
||||
|
||||
TP_printk("name=%s, syncpt_base=%d, syncpt_max=%d",
|
||||
__entry->name, __entry->syncpt_base, __entry->syncpt_max)
|
||||
__get_str(name), __entry->syncpt_base, __entry->syncpt_max)
|
||||
);
|
||||
|
||||
TRACE_EVENT(host1x_channel_submit_complete,
|
||||
|
|
@ -182,19 +184,19 @@ TRACE_EVENT(host1x_channel_submit_complete,
|
|||
TP_ARGS(name, count, thresh),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(const char *, name)
|
||||
__string(name, name)
|
||||
__field(int, count)
|
||||
__field(u32, thresh)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->name = name;
|
||||
__assign_str(name);
|
||||
__entry->count = count;
|
||||
__entry->thresh = thresh;
|
||||
),
|
||||
|
||||
TP_printk("name=%s, count=%d, thresh=%d",
|
||||
__entry->name, __entry->count, __entry->thresh)
|
||||
__get_str(name), __entry->count, __entry->thresh)
|
||||
);
|
||||
|
||||
TRACE_EVENT(host1x_wait_cdma,
|
||||
|
|
@ -203,16 +205,16 @@ TRACE_EVENT(host1x_wait_cdma,
|
|||
TP_ARGS(name, eventid),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(const char *, name)
|
||||
__string(name, name)
|
||||
__field(u32, eventid)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->name = name;
|
||||
__assign_str(name);
|
||||
__entry->eventid = eventid;
|
||||
),
|
||||
|
||||
TP_printk("name=%s, event=%d", __entry->name, __entry->eventid)
|
||||
TP_printk("name=%s, event=%d", __get_str(name), __entry->eventid)
|
||||
);
|
||||
|
||||
TRACE_EVENT(host1x_syncpt_load_min,
|
||||
|
|
|
|||
|
|
@ -304,6 +304,7 @@ struct drm_tegra_cmdbuf {
|
|||
* struct drm_tegra_reloc - GEM object relocation structure
|
||||
*/
|
||||
struct drm_tegra_reloc {
|
||||
/** @cmdbuf: cmd information */
|
||||
struct {
|
||||
/**
|
||||
* @cmdbuf.handle:
|
||||
|
|
@ -321,6 +322,7 @@ struct drm_tegra_reloc {
|
|||
*/
|
||||
__u32 offset;
|
||||
} cmdbuf;
|
||||
/** @target: relocate target information */
|
||||
struct {
|
||||
/**
|
||||
* @target.handle:
|
||||
|
|
@ -778,6 +780,9 @@ struct drm_tegra_channel_unmap {
|
|||
/* Submission */
|
||||
|
||||
/**
|
||||
* define DRM_TEGRA_SUBMIT_RELOC_SECTOR_LAYOUT - \
|
||||
* Select sector layout swizzling for in-memory buffers.
|
||||
*
|
||||
* Specify that bit 39 of the patched-in address should be set to switch
|
||||
* swizzling between Tegra and non-Tegra sector layout on systems that store
|
||||
* surfaces in system memory in non-Tegra sector layout.
|
||||
|
|
@ -830,16 +835,27 @@ struct drm_tegra_submit_buf {
|
|||
};
|
||||
|
||||
/**
|
||||
* define DRM_TEGRA_SUBMIT_CMD_GATHER_UPTR - \
|
||||
* Execute Host1x opcodes from user pointer.
|
||||
*
|
||||
* Execute `words` words of Host1x opcodes specified in the `gather_data_ptr`
|
||||
* buffer. Each GATHER_UPTR command uses successive words from the buffer.
|
||||
*/
|
||||
#define DRM_TEGRA_SUBMIT_CMD_GATHER_UPTR 0
|
||||
|
||||
/**
|
||||
* define DRM_TEGRA_SUBMIT_CMD_WAIT_SYNCPT - \
|
||||
* Wait for syncpoint (absolute).
|
||||
*
|
||||
* Wait for a syncpoint to reach a value before continuing with further
|
||||
* commands.
|
||||
*/
|
||||
#define DRM_TEGRA_SUBMIT_CMD_WAIT_SYNCPT 1
|
||||
|
||||
/**
|
||||
* define DRM_TEGRA_SUBMIT_CMD_WAIT_SYNCPT_RELATIVE - \
|
||||
* Wait for syncpoint (relative).
|
||||
*
|
||||
* Wait for a syncpoint to reach a value before continuing with further
|
||||
* commands. The threshold is calculated relative to the start of the job.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user