summaryrefslogtreecommitdiffstats
path: root/sys/dev/pci/drm/include
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci/drm/include')
-rw-r--r--sys/dev/pci/drm/include/acpi/acpi_bus.h0
-rw-r--r--sys/dev/pci/drm/include/asm/byteorder.h9
-rw-r--r--sys/dev/pci/drm/include/asm/cpufeature.h34
-rw-r--r--sys/dev/pci/drm/include/asm/current.h8
-rw-r--r--sys/dev/pci/drm/include/asm/fpu/api.h2
-rw-r--r--sys/dev/pci/drm/include/asm/ioctl.h0
-rw-r--r--sys/dev/pci/drm/include/asm/preempt.h8
-rw-r--r--sys/dev/pci/drm/include/asm/set_memory.h6
-rw-r--r--sys/dev/pci/drm/include/asm/smp.h20
-rw-r--r--sys/dev/pci/drm/include/asm/thread_info.h8
-rw-r--r--sys/dev/pci/drm/include/drm/amd_asic_type.h51
-rw-r--r--sys/dev/pci/drm/include/drm/drmP.h324
-rw-r--r--sys/dev/pci/drm/include/drm/drm_agpsupport.h47
-rw-r--r--sys/dev/pci/drm/include/drm/drm_atomic.h247
-rw-r--r--sys/dev/pci/drm/include/drm/drm_atomic_helper.h64
-rw-r--r--sys/dev/pci/drm/include/drm/drm_atomic_state_helper.h95
-rw-r--r--sys/dev/pci/drm/include/drm/drm_atomic_uapi.h58
-rw-r--r--sys/dev/pci/drm/include/drm/drm_audio_component.h8
-rw-r--r--sys/dev/pci/drm/include/drm/drm_auth.h115
-rw-r--r--sys/dev/pci/drm/include/drm/drm_blend.h6
-rw-r--r--sys/dev/pci/drm/include/drm/drm_bridge.h643
-rw-r--r--sys/dev/pci/drm/include/drm/drm_cache.h12
-rw-r--r--sys/dev/pci/drm/include/drm/drm_client.h193
-rw-r--r--sys/dev/pci/drm/include/drm/drm_color_mgmt.h54
-rw-r--r--sys/dev/pci/drm/include/drm/drm_connector.h564
-rw-r--r--sys/dev/pci/drm/include/drm/drm_crtc.h174
-rw-r--r--sys/dev/pci/drm/include/drm/drm_crtc_helper.h25
-rw-r--r--sys/dev/pci/drm/include/drm/drm_damage_helper.h102
-rw-r--r--sys/dev/pci/drm/include/drm/drm_debugfs.h103
-rw-r--r--sys/dev/pci/drm/include/drm/drm_device.h394
-rw-r--r--sys/dev/pci/drm/include/drm/drm_dp_helper.h380
-rw-r--r--sys/dev/pci/drm/include/drm/drm_dp_mst_helper.h386
-rw-r--r--sys/dev/pci/drm/include/drm/drm_drv.h806
-rw-r--r--sys/dev/pci/drm/include/drm/drm_dsc.h609
-rw-r--r--sys/dev/pci/drm/include/drm/drm_edid.h66
-rw-r--r--sys/dev/pci/drm/include/drm/drm_encoder.h15
-rw-r--r--sys/dev/pci/drm/include/drm/drm_encoder_slave.h192
-rw-r--r--sys/dev/pci/drm/include/drm/drm_fb_helper.h224
-rw-r--r--sys/dev/pci/drm/include/drm/drm_file.h50
-rw-r--r--sys/dev/pci/drm/include/drm/drm_flip_work.h92
-rw-r--r--sys/dev/pci/drm/include/drm/drm_format_helper.h31
-rw-r--r--sys/dev/pci/drm/include/drm/drm_fourcc.h280
-rw-r--r--sys/dev/pci/drm/include/drm/drm_framebuffer.h38
-rw-r--r--sys/dev/pci/drm/include/drm/drm_gem.h242
-rw-r--r--sys/dev/pci/drm/include/drm/drm_gem_cma_helper.h1
-rw-r--r--sys/dev/pci/drm/include/drm/drm_gem_framebuffer_helper.h4
-rw-r--r--sys/dev/pci/drm/include/drm/drm_global.h53
-rw-r--r--sys/dev/pci/drm/include/drm/drm_hashtab.h30
-rw-r--r--sys/dev/pci/drm/include/drm/drm_hdcp.h261
-rw-r--r--sys/dev/pci/drm/include/drm/drm_ioctl.h156
-rw-r--r--sys/dev/pci/drm/include/drm/drm_lease.h16
-rw-r--r--sys/dev/pci/drm/include/drm/drm_legacy.h235
-rw-r--r--sys/dev/pci/drm/include/drm/drm_mipi_dsi.h13
-rw-r--r--sys/dev/pci/drm/include/drm/drm_mode_config.h93
-rw-r--r--sys/dev/pci/drm/include/drm/drm_modes.h55
-rw-r--r--sys/dev/pci/drm/include/drm/drm_modeset_helper.h6
-rw-r--r--sys/dev/pci/drm/include/drm/drm_modeset_helper_vtables.h144
-rw-r--r--sys/dev/pci/drm/include/drm/drm_modeset_lock.h70
-rw-r--r--sys/dev/pci/drm/include/drm/drm_panel.h226
-rw-r--r--sys/dev/pci/drm/include/drm/drm_pci.h63
-rw-r--r--sys/dev/pci/drm/include/drm/drm_plane.h96
-rw-r--r--sys/dev/pci/drm/include/drm/drm_plane_helper.h35
-rw-r--r--sys/dev/pci/drm/include/drm/drm_prime.h47
-rw-r--r--sys/dev/pci/drm/include/drm/drm_print.h366
-rw-r--r--sys/dev/pci/drm/include/drm/drm_probe_helper.h27
-rw-r--r--sys/dev/pci/drm/include/drm/drm_property.h5
-rw-r--r--sys/dev/pci/drm/include/drm/drm_rect.h39
-rw-r--r--sys/dev/pci/drm/include/drm/drm_scdc_helper.h6
-rw-r--r--sys/dev/pci/drm/include/drm/drm_self_refresh_helper.h21
-rw-r--r--sys/dev/pci/drm/include/drm/drm_syncobj.h35
-rw-r--r--sys/dev/pci/drm/include/drm/drm_sysfs.h10
-rw-r--r--sys/dev/pci/drm/include/drm/drm_util.h83
-rw-r--r--sys/dev/pci/drm/include/drm/drm_utils.h4
-rw-r--r--sys/dev/pci/drm/include/drm/drm_vblank.h60
-rw-r--r--sys/dev/pci/drm/include/drm/drm_vma_manager.h59
-rw-r--r--sys/dev/pci/drm/include/drm/drm_writeback.h21
-rw-r--r--sys/dev/pci/drm/include/drm/gpu_scheduler.h87
-rw-r--r--sys/dev/pci/drm/include/drm/i2c/ch7006.h86
-rw-r--r--sys/dev/pci/drm/include/drm/i2c/sil164.h63
-rw-r--r--sys/dev/pci/drm/include/drm/i915_component.h7
-rw-r--r--sys/dev/pci/drm/include/drm/i915_drm.h10
-rw-r--r--sys/dev/pci/drm/include/drm/i915_mei_hdcp_interface.h50
-rw-r--r--sys/dev/pci/drm/include/drm/i915_pciids.h234
-rw-r--r--sys/dev/pci/drm/include/drm/intel-gtt.h21
-rw-r--r--sys/dev/pci/drm/include/drm/task_barrier.h119
-rw-r--r--sys/dev/pci/drm/include/drm/ttm/ttm_bo_api.h197
-rw-r--r--sys/dev/pci/drm/include/drm/ttm/ttm_bo_driver.h132
-rw-r--r--sys/dev/pci/drm/include/drm/ttm/ttm_execbuf_util.h5
-rw-r--r--sys/dev/pci/drm/include/drm/ttm/ttm_memory.h5
-rw-r--r--sys/dev/pci/drm/include/drm/ttm/ttm_page_alloc.h2
-rw-r--r--sys/dev/pci/drm/include/drm/ttm/ttm_set_memory.h1
-rw-r--r--sys/dev/pci/drm/include/drm/ttm/ttm_tt.h2
-rw-r--r--sys/dev/pci/drm/include/generated/autoconf.h48
-rw-r--r--sys/dev/pci/drm/include/linux/agp_backend.h2
-rw-r--r--sys/dev/pci/drm/include/linux/ascii85.h0
-rw-r--r--sys/dev/pci/drm/include/linux/atomic.h36
-rw-r--r--sys/dev/pci/drm/include/linux/average.h38
-rw-r--r--sys/dev/pci/drm/include/linux/backlight.h5
-rw-r--r--sys/dev/pci/drm/include/linux/bitfield.h16
-rw-r--r--sys/dev/pci/drm/include/linux/bitmap.h28
-rw-r--r--sys/dev/pci/drm/include/linux/bitops.h8
-rw-r--r--sys/dev/pci/drm/include/linux/bits.h0
-rw-r--r--sys/dev/pci/drm/include/linux/bottom_half.h2
-rw-r--r--sys/dev/pci/drm/include/linux/build_bug.h0
-rw-r--r--sys/dev/pci/drm/include/linux/byteorder/generic.h0
-rw-r--r--sys/dev/pci/drm/include/linux/compiler.h20
-rw-r--r--sys/dev/pci/drm/include/linux/completion.h39
-rw-r--r--sys/dev/pci/drm/include/linux/component.h8
-rw-r--r--sys/dev/pci/drm/include/linux/debugfs.h9
-rw-r--r--sys/dev/pci/drm/include/linux/debugobjects.h0
-rw-r--r--sys/dev/pci/drm/include/linux/delay.h2
-rw-r--r--sys/dev/pci/drm/include/linux/device.h25
-rw-r--r--sys/dev/pci/drm/include/linux/dma-buf.h17
-rw-r--r--sys/dev/pci/drm/include/linux/dma-fence-chain.h9
-rw-r--r--sys/dev/pci/drm/include/linux/dma-fence.h48
-rw-r--r--sys/dev/pci/drm/include/linux/dma-mapping.h3
-rw-r--r--sys/dev/pci/drm/include/linux/dma-resv.h (renamed from sys/dev/pci/drm/include/linux/reservation.h)197
-rw-r--r--sys/dev/pci/drm/include/linux/errno.h1
-rw-r--r--sys/dev/pci/drm/include/linux/fb.h48
-rw-r--r--sys/dev/pci/drm/include/linux/firmware.h1
-rw-r--r--sys/dev/pci/drm/include/linux/fs.h2
-rw-r--r--sys/dev/pci/drm/include/linux/ftrace.h8
-rw-r--r--sys/dev/pci/drm/include/linux/gfp.h2
-rw-r--r--sys/dev/pci/drm/include/linux/hashtable.h3
-rw-r--r--sys/dev/pci/drm/include/linux/hdmi.h108
-rw-r--r--sys/dev/pci/drm/include/linux/highmem.h3
-rw-r--r--sys/dev/pci/drm/include/linux/hmm.h0
-rw-r--r--sys/dev/pci/drm/include/linux/i2c.h11
-rw-r--r--sys/dev/pci/drm/include/linux/idr.h5
-rw-r--r--sys/dev/pci/drm/include/linux/init.h8
-rw-r--r--sys/dev/pci/drm/include/linux/intel-iommu.h8
-rw-r--r--sys/dev/pci/drm/include/linux/interrupt.h17
-rw-r--r--sys/dev/pci/drm/include/linux/io-64-nonatomic-lo-hi.h0
-rw-r--r--sys/dev/pci/drm/include/linux/io.h9
-rw-r--r--sys/dev/pci/drm/include/linux/ipc.h8
-rw-r--r--sys/dev/pci/drm/include/linux/kallsyms.h8
-rw-r--r--sys/dev/pci/drm/include/linux/kconfig.h12
-rw-r--r--sys/dev/pci/drm/include/linux/kernel.h23
-rw-r--r--sys/dev/pci/drm/include/linux/kernfs.h9
-rw-r--r--sys/dev/pci/drm/include/linux/kgdb.h1
-rw-r--r--sys/dev/pci/drm/include/linux/kmemleak.h8
-rw-r--r--sys/dev/pci/drm/include/linux/kref.h19
-rw-r--r--sys/dev/pci/drm/include/linux/ktime.h8
-rw-r--r--sys/dev/pci/drm/include/linux/list.h25
-rw-r--r--sys/dev/pci/drm/include/linux/llist.h24
-rw-r--r--sys/dev/pci/drm/include/linux/lockdep.h21
-rw-r--r--sys/dev/pci/drm/include/linux/log2.h2
-rw-r--r--sys/dev/pci/drm/include/linux/math64.h17
-rw-r--r--sys/dev/pci/drm/include/linux/media-bus-format.h8
-rw-r--r--sys/dev/pci/drm/include/linux/mempolicy.h8
-rw-r--r--sys/dev/pci/drm/include/linux/mm.h4
-rw-r--r--sys/dev/pci/drm/include/linux/mm_types.h11
-rw-r--r--sys/dev/pci/drm/include/linux/mmzone.h8
-rw-r--r--sys/dev/pci/drm/include/linux/mod_devicetable.h10
-rw-r--r--sys/dev/pci/drm/include/linux/module.h12
-rw-r--r--sys/dev/pci/drm/include/linux/moduleparam.h1
-rw-r--r--sys/dev/pci/drm/include/linux/mutex.h4
-rw-r--r--sys/dev/pci/drm/include/linux/nmi.h0
-rw-r--r--sys/dev/pci/drm/include/linux/of.h15
-rw-r--r--sys/dev/pci/drm/include/linux/overflow.h3
-rw-r--r--sys/dev/pci/drm/include/linux/pagemap.h9
-rw-r--r--sys/dev/pci/drm/include/linux/pci.h111
-rw-r--r--sys/dev/pci/drm/include/linux/perf_event.h2
-rw-r--r--sys/dev/pci/drm/include/linux/pfn.h0
-rw-r--r--sys/dev/pci/drm/include/linux/pid.h2
-rw-r--r--sys/dev/pci/drm/include/linux/pm.h3
-rw-r--r--sys/dev/pci/drm/include/linux/pm_qos.h4
-rw-r--r--sys/dev/pci/drm/include/linux/pm_runtime.h8
-rw-r--r--sys/dev/pci/drm/include/linux/poison.h9
-rw-r--r--sys/dev/pci/drm/include/linux/poll.h1
-rw-r--r--sys/dev/pci/drm/include/linux/preempt.h3
-rw-r--r--sys/dev/pci/drm/include/linux/prime_numbers.h0
-rw-r--r--sys/dev/pci/drm/include/linux/printk.h45
-rw-r--r--sys/dev/pci/drm/include/linux/pseudo_fs.h0
-rw-r--r--sys/dev/pci/drm/include/linux/radix-tree.h1
-rw-r--r--sys/dev/pci/drm/include/linux/random.h6
-rw-r--r--sys/dev/pci/drm/include/linux/rbtree.h23
-rw-r--r--sys/dev/pci/drm/include/linux/rculist.h15
-rw-r--r--sys/dev/pci/drm/include/linux/rcupdate.h12
-rw-r--r--sys/dev/pci/drm/include/linux/refcount.h28
-rw-r--r--sys/dev/pci/drm/include/linux/rwsem.h0
-rw-r--r--sys/dev/pci/drm/include/linux/scatterlist.h14
-rw-r--r--sys/dev/pci/drm/include/linux/sched.h4
-rw-r--r--sys/dev/pci/drm/include/linux/sched/clock.h2
-rw-r--r--sys/dev/pci/drm/include/linux/sched/signal.h1
-rw-r--r--sys/dev/pci/drm/include/linux/sched/task.h0
-rw-r--r--sys/dev/pci/drm/include/linux/sem.h8
-rw-r--r--sys/dev/pci/drm/include/linux/semaphore.h9
-rw-r--r--sys/dev/pci/drm/include/linux/shmem_fs.h10
-rw-r--r--sys/dev/pci/drm/include/linux/sizes.h10
-rw-r--r--sys/dev/pci/drm/include/linux/smp.h3
-rw-r--r--sys/dev/pci/drm/include/linux/spinlock.h23
-rw-r--r--sys/dev/pci/drm/include/linux/srcu.h14
-rw-r--r--sys/dev/pci/drm/include/linux/stackdepot.h8
-rw-r--r--sys/dev/pci/drm/include/linux/stacktrace.h0
-rw-r--r--sys/dev/pci/drm/include/linux/stat.h0
-rw-r--r--sys/dev/pci/drm/include/linux/string.h3
-rw-r--r--sys/dev/pci/drm/include/linux/suspend.h0
-rw-r--r--sys/dev/pci/drm/include/linux/swap.h12
-rw-r--r--sys/dev/pci/drm/include/linux/syscalls.h0
-rw-r--r--sys/dev/pci/drm/include/linux/sysfs.h18
-rw-r--r--sys/dev/pci/drm/include/linux/sysrq.h15
-rw-r--r--sys/dev/pci/drm/include/linux/thread_info.h8
-rw-r--r--sys/dev/pci/drm/include/linux/time.h6
-rw-r--r--sys/dev/pci/drm/include/linux/timekeeping.h7
-rw-r--r--sys/dev/pci/drm/include/linux/timer.h3
-rw-r--r--sys/dev/pci/drm/include/linux/tracepoint.h2
-rw-r--r--sys/dev/pci/drm/include/linux/types.h2
-rw-r--r--sys/dev/pci/drm/include/linux/uaccess.h12
-rw-r--r--sys/dev/pci/drm/include/linux/uio.h0
-rw-r--r--sys/dev/pci/drm/include/linux/utsname.h0
-rw-r--r--sys/dev/pci/drm/include/linux/vga_switcheroo.h19
-rw-r--r--sys/dev/pci/drm/include/linux/vgaarb.h6
-rw-r--r--sys/dev/pci/drm/include/linux/wait.h10
-rw-r--r--sys/dev/pci/drm/include/linux/wait_bit.h19
-rw-r--r--sys/dev/pci/drm/include/linux/workqueue.h22
-rw-r--r--sys/dev/pci/drm/include/linux/ww_mutex.h2
-rw-r--r--sys/dev/pci/drm/include/linux/xarray.h58
-rw-r--r--sys/dev/pci/drm/include/media/cec-notifier.h6
-rw-r--r--sys/dev/pci/drm/include/trace/define_trace.h0
-rw-r--r--sys/dev/pci/drm/include/trace/events/dma_fence.h14
-rw-r--r--sys/dev/pci/drm/include/uapi/drm/amdgpu_drm.h91
-rw-r--r--sys/dev/pci/drm/include/uapi/drm/drm.h40
-rw-r--r--sys/dev/pci/drm/include/uapi/drm/drm_fourcc.h227
-rw-r--r--sys/dev/pci/drm/include/uapi/drm/drm_mode.h144
-rw-r--r--sys/dev/pci/drm/include/uapi/drm/i915_drm.h655
-rw-r--r--sys/dev/pci/drm/include/uapi/drm/radeon_drm.h2
-rw-r--r--sys/dev/pci/drm/include/uapi/linux/ioctl.h0
-rw-r--r--sys/dev/pci/drm/include/uapi/linux/kfd_ioctl.h535
-rw-r--r--sys/dev/pci/drm/include/video/mipi_display.h8
230 files changed, 11134 insertions, 2409 deletions
diff --git a/sys/dev/pci/drm/include/acpi/acpi_bus.h b/sys/dev/pci/drm/include/acpi/acpi_bus.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sys/dev/pci/drm/include/acpi/acpi_bus.h
diff --git a/sys/dev/pci/drm/include/asm/byteorder.h b/sys/dev/pci/drm/include/asm/byteorder.h
index 75f771e2cd9..d2726354179 100644
--- a/sys/dev/pci/drm/include/asm/byteorder.h
+++ b/sys/dev/pci/drm/include/asm/byteorder.h
@@ -4,19 +4,28 @@
#define _ASM_BYTEORDER_H
#include <sys/endian.h>
+#include <linux/types.h>
#define le16_to_cpu(x) letoh16(x)
#define le32_to_cpu(x) letoh32(x)
+#define le64_to_cpu(x) letoh64(x)
#define be16_to_cpu(x) betoh16(x)
#define be32_to_cpu(x) betoh32(x)
+#define be64_to_cpu(x) betoh64(x)
#define le16_to_cpup(x) lemtoh16(x)
#define le32_to_cpup(x) lemtoh32(x)
+#define le64_to_cpup(x) lemtoh64(x)
#define be16_to_cpup(x) bemtoh16(x)
#define be32_to_cpup(x) bemtoh32(x)
+#define be64_to_cpup(x) bemtoh64(x)
#define get_unaligned_le32(x) lemtoh32(x)
#define cpu_to_le16(x) htole16(x)
#define cpu_to_le32(x) htole32(x)
+#define cpu_to_le64(x) htole64(x)
#define cpu_to_be16(x) htobe16(x)
#define cpu_to_be32(x) htobe32(x)
+#define cpu_to_be64(x) htobe64(x)
+
+#define swab16(x) swap16(x)
#endif
diff --git a/sys/dev/pci/drm/include/asm/cpufeature.h b/sys/dev/pci/drm/include/asm/cpufeature.h
new file mode 100644
index 00000000000..bdeb54044aa
--- /dev/null
+++ b/sys/dev/pci/drm/include/asm/cpufeature.h
@@ -0,0 +1,34 @@
+/* Public domain. */
+
+#ifndef _ASM_CPUFEATURE_H
+#define _ASM_CPUFEATURE_H
+
+#if defined(__amd64__) || defined(__i386__)
+
+#define X86_FEATURE_CLFLUSH 1
+#define X86_FEATURE_XMM4_1 2
+#define X86_FEATURE_PAT 3
+#define X86_FEATURE_HYPERVISOR 4
+
+static inline bool
+static_cpu_has(uint16_t f)
+{
+ switch (f) {
+ case X86_FEATURE_CLFLUSH:
+ return curcpu()->ci_cflushsz != 0;
+ case X86_FEATURE_XMM4_1:
+ return (cpu_ecxfeature & CPUIDECX_SSE41) != 0;
+ case X86_FEATURE_PAT:
+ return (curcpu()->ci_feature_flags & CPUID_PAT) != 0;
+ case X86_FEATURE_HYPERVISOR:
+ return (cpu_ecxfeature & CPUIDECX_HV) != 0;
+ default:
+ return false;
+ }
+}
+
+#define boot_cpu_has(x) static_cpu_has(x)
+
+#endif
+
+#endif
diff --git a/sys/dev/pci/drm/include/asm/current.h b/sys/dev/pci/drm/include/asm/current.h
new file mode 100644
index 00000000000..30263918de8
--- /dev/null
+++ b/sys/dev/pci/drm/include/asm/current.h
@@ -0,0 +1,8 @@
+/* Public domain. */
+
+#ifndef _ASM_CURRENT_H
+#define _ASM_CURRENT_H
+
+#define current curproc
+
+#endif
diff --git a/sys/dev/pci/drm/include/asm/fpu/api.h b/sys/dev/pci/drm/include/asm/fpu/api.h
index 882ea6f5ec8..8caad859860 100644
--- a/sys/dev/pci/drm/include/asm/fpu/api.h
+++ b/sys/dev/pci/drm/include/asm/fpu/api.h
@@ -3,6 +3,8 @@
#ifndef _ASM_FPU_API_H
#define _ASM_FPU_API_H
+#include <linux/bottom_half.h>
+
#ifdef __i386__
#include <machine/npx.h>
#endif
diff --git a/sys/dev/pci/drm/include/asm/ioctl.h b/sys/dev/pci/drm/include/asm/ioctl.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sys/dev/pci/drm/include/asm/ioctl.h
diff --git a/sys/dev/pci/drm/include/asm/preempt.h b/sys/dev/pci/drm/include/asm/preempt.h
new file mode 100644
index 00000000000..5a55e454af1
--- /dev/null
+++ b/sys/dev/pci/drm/include/asm/preempt.h
@@ -0,0 +1,8 @@
+/* Public domain. */
+
+#ifndef _ASM_PREEMPT_H
+#define _ASM_PREEMPT_H
+
+#include <linux/thread_info.h>
+
+#endif
diff --git a/sys/dev/pci/drm/include/asm/set_memory.h b/sys/dev/pci/drm/include/asm/set_memory.h
index e78088fd66e..5fced579566 100644
--- a/sys/dev/pci/drm/include/asm/set_memory.h
+++ b/sys/dev/pci/drm/include/asm/set_memory.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: set_memory.h,v 1.1 2019/04/14 10:14:52 jsg Exp $ */
+/* $OpenBSD: set_memory.h,v 1.2 2020/06/08 04:48:14 jsg Exp $ */
/*
* Copyright (c) 2013, 2014, 2015 Mark Kettenis
*
@@ -19,6 +19,10 @@
#define _ASM_SET_MEMORY_H
#include <sys/atomic.h>
+
+#include <sys/param.h> /* for PAGE_SIZE on i386 */
+#include <uvm/uvm_extern.h>
+
#include <machine/pmap.h>
#if defined(__amd64__) || defined(__i386__)
diff --git a/sys/dev/pci/drm/include/asm/smp.h b/sys/dev/pci/drm/include/asm/smp.h
new file mode 100644
index 00000000000..a50485db7f5
--- /dev/null
+++ b/sys/dev/pci/drm/include/asm/smp.h
@@ -0,0 +1,20 @@
+/* Public domain. */
+
+#ifndef _ASM_SMP_H
+#define _ASM_SMP_H
+
+#if defined(__i386__) || defined(__amd64__)
+
+#include <machine/cpu.h>
+
+static inline int
+wbinvd_on_all_cpus(void)
+{
+ /* XXX single cpu only */
+ wbinvd();
+ return 0;
+}
+
+#endif
+
+#endif
diff --git a/sys/dev/pci/drm/include/asm/thread_info.h b/sys/dev/pci/drm/include/asm/thread_info.h
new file mode 100644
index 00000000000..e8c24b4ef61
--- /dev/null
+++ b/sys/dev/pci/drm/include/asm/thread_info.h
@@ -0,0 +1,8 @@
+/* Public domain. */
+
+#ifndef _ASM_THREAD_INFO_H
+#define _ASM_THREAD_INFO_H
+
+#include <asm/cpufeature.h>
+
+#endif
diff --git a/sys/dev/pci/drm/include/drm/amd_asic_type.h b/sys/dev/pci/drm/include/drm/amd_asic_type.h
index dd63d08cc54..b1230e33d50 100644
--- a/sys/dev/pci/drm/include/drm/amd_asic_type.h
+++ b/sys/dev/pci/drm/include/drm/amd_asic_type.h
@@ -27,29 +27,36 @@
*/
enum amd_asic_type {
CHIP_TAHITI = 0,
- CHIP_PITCAIRN,
- CHIP_VERDE,
- CHIP_OLAND,
- CHIP_HAINAN,
- CHIP_BONAIRE,
- CHIP_KAVERI,
- CHIP_KABINI,
- CHIP_HAWAII,
- CHIP_MULLINS,
- CHIP_TOPAZ,
- CHIP_TONGA,
- CHIP_FIJI,
- CHIP_CARRIZO,
- CHIP_STONEY,
- CHIP_POLARIS10,
- CHIP_POLARIS11,
- CHIP_POLARIS12,
- CHIP_VEGAM,
- CHIP_VEGA10,
- CHIP_VEGA12,
- CHIP_VEGA20,
- CHIP_RAVEN,
+ CHIP_PITCAIRN, /* 1 */
+ CHIP_VERDE, /* 2 */
+ CHIP_OLAND, /* 3 */
+ CHIP_HAINAN, /* 4 */
+ CHIP_BONAIRE, /* 5 */
+ CHIP_KAVERI, /* 6 */
+ CHIP_KABINI, /* 7 */
+ CHIP_HAWAII, /* 8 */
+ CHIP_MULLINS, /* 9 */
+ CHIP_TOPAZ, /* 10 */
+ CHIP_TONGA, /* 11 */
+ CHIP_FIJI, /* 12 */
+ CHIP_CARRIZO, /* 13 */
+ CHIP_STONEY, /* 14 */
+ CHIP_POLARIS10, /* 15 */
+ CHIP_POLARIS11, /* 16 */
+ CHIP_POLARIS12, /* 17 */
+ CHIP_VEGAM, /* 18 */
+ CHIP_VEGA10, /* 19 */
+ CHIP_VEGA12, /* 20 */
+ CHIP_VEGA20, /* 21 */
+ CHIP_RAVEN, /* 22 */
+ CHIP_ARCTURUS, /* 23 */
+ CHIP_RENOIR, /* 24 */
+ CHIP_NAVI10, /* 25 */
+ CHIP_NAVI14, /* 26 */
+ CHIP_NAVI12, /* 27 */
CHIP_LAST,
};
+extern const char *amdgpu_asic_name[];
+
#endif /*__AMD_ASIC_TYPE_H__ */
diff --git a/sys/dev/pci/drm/include/drm/drmP.h b/sys/dev/pci/drm/include/drm/drmP.h
deleted file mode 100644
index 832d016032b..00000000000
--- a/sys/dev/pci/drm/include/drm/drmP.h
+++ /dev/null
@@ -1,324 +0,0 @@
-/* $OpenBSD: drmP.h,v 1.8 2020/03/04 21:19:15 kettenis Exp $ */
-/* drmP.h -- Private header for Direct Rendering Manager -*- linux-c -*-
- * Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com
- */
-/*-
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- *
- */
-
-#ifndef _DRM_P_H_
-#define _DRM_P_H_
-
-#if defined(_KERNEL) || defined(__KERNEL__)
-
-//#define DRMDEBUG
-
-#include <sys/param.h>
-#include <sys/queue.h>
-#include <sys/malloc.h>
-#include <sys/pool.h>
-#include <sys/kernel.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/mutex.h>
-#include <sys/tree.h>
-#include <sys/endian.h>
-#include <sys/stdint.h>
-#include <sys/memrange.h>
-#include <sys/extent.h>
-#include <sys/rwlock.h>
-
-#ifdef DDB
-#include <ddb/db_var.h>
-#endif
-
-#include <uvm/uvm_extern.h>
-#include <uvm/uvm_object.h>
-
-#include <dev/pci/pcidevs.h>
-#include <dev/pci/pcivar.h>
-#include <dev/pci/agpvar.h>
-#include <machine/bus.h>
-
-#include <linux/agp_backend.h>
-#include <linux/cdev.h>
-#include <linux/dma-mapping.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/highmem.h>
-#include <linux/idr.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/jiffies.h>
-#include <linux/kernel.h>
-#include <linux/kref.h>
-#include <linux/miscdevice.h>
-#include <linux/mm.h>
-#include <linux/mutex.h>
-#include <linux/platform_device.h>
-#include <linux/poll.h>
-#include <linux/ratelimit.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/vmalloc.h>
-#include <linux/workqueue.h>
-#include <linux/dma-fence.h>
-#include <linux/module.h>
-
-#include <dev/pci/drm/drm_linux.h>
-#include <linux/list.h>
-#include <linux/pci.h>
-/* these match drm_os_linux.h includes */
-#include <linux/interrupt.h>
-#include <linux/sched/signal.h>
-#include <linux/delay.h>
-
-#include <uapi/drm/drm.h>
-#include <uapi/drm/drm_mode.h>
-
-#include <drm/drm_crtc.h>
-#include <drm/drm_fourcc.h>
-#include <drm/drm_global.h>
-#include <drm/drm_hashtab.h>
-#include <drm/drm_mm.h>
-#include <drm/drm_drv.h>
-#include <drm/drm_prime.h>
-#include <drm/drm_print.h>
-#include <drm/drm_file.h>
-#include <drm/drm_ioctl.h>
-#include <drm/drm_vblank.h>
-#include <drm/drm_irq.h>
-#include <drm/drm_device.h>
-
-struct fb_cmap;
-struct fb_fillrect;
-struct fb_copyarea;
-struct fb_image;
-
- /* Internal types and structures */
-#define DRM_IF_VERSION(maj, min) (maj << 16 | min)
-
-#define DRM_CURRENTPID curproc->p_p->ps_pid
-
-/* DRM_SUSER returns true if the user is superuser */
-#define DRM_SUSER(p) (suser(p) == 0)
-#define DRM_MTRR_WC MDF_WRITECOMBINE
-
-#define drm_msleep(x) mdelay(x)
-
-extern struct cfdriver drm_cd;
-
-/* freebsd compat */
-#define TAILQ_CONCAT(head1, head2, field) do { \
- if (!TAILQ_EMPTY(head2)) { \
- *(head1)->tqh_last = (head2)->tqh_first; \
- (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
- (head1)->tqh_last = (head2)->tqh_last; \
- TAILQ_INIT((head2)); \
- } \
-} while (0)
-
-#define DRM_COPY_TO_USER(user, kern, size) copyout(kern, user, size)
-
-#define DRM_UDELAY(udelay) DELAY(udelay)
-
-static inline bool
-drm_can_sleep(void)
-{
-#if defined(__i386__) || defined(__amd64__)
- if (pagefault_disabled() || in_dbg_master() || irqs_disabled())
-#else
- if (in_dbg_master() || irqs_disabled())
-#endif
- return false;
- return true;
-}
-
-#define DRM_WAIT_ON(ret, wq, timo, condition) do { \
- ret = wait_event_interruptible_timeout(wq, condition, timo); \
- if (ret == 0) \
- ret = -EBUSY; \
- if (ret > 0) \
- ret = 0; \
-} while (0)
-
-struct drm_pcidev {
- uint16_t vendor;
- uint16_t device;
- uint16_t subvendor;
- uint16_t subdevice;
- uint32_t class;
- uint32_t class_mask;
- unsigned long driver_data;
-};
-
-struct drm_dmamem {
- bus_dmamap_t map;
- caddr_t kva;
- bus_size_t size;
- int nsegs;
- bus_dma_segment_t segs[1];
-};
-
-typedef struct drm_dma_handle {
- struct drm_dmamem *mem;
- dma_addr_t busaddr;
- void *vaddr;
- size_t size;
-} drm_dma_handle_t;
-
-struct drm_agp_head {
- struct agp_softc *agpdev;
- const char *chipset;
- TAILQ_HEAD(agp_memlist, drm_agp_mem) memory;
- struct agp_info info;
- unsigned long base;
- unsigned long mode;
- unsigned long page_mask;
- int acquired;
- int cant_use_aperture;
- int enabled;
- int mtrr;
-};
-
-/* Flags and return codes for get_vblank_timestamp() driver function. */
-#define DRM_CALLED_FROM_VBLIRQ 1
-
-/* get_scanout_position() return flags */
-#define DRM_SCANOUTPOS_VALID (1 << 0)
-#define DRM_SCANOUTPOS_IN_VBLANK (1 << 1)
-#define DRM_SCANOUTPOS_ACCURATE (1 << 2)
-
-struct drm_attach_args {
- struct drm_device *drm;
- struct drm_driver *driver;
- char *busid;
- bus_dma_tag_t dmat;
- bus_space_tag_t bst;
- size_t busid_len;
- int is_agp;
- struct pci_attach_args *pa;
- int primary;
-};
-
-#define DRMDEVCF_PRIMARY 0
-#define drmdevcf_primary cf_loc[DRMDEVCF_PRIMARY] /* spec'd as primary? */
-#define DRMDEVCF_PRIMARY_UNK -1
-
-void drm_linux_init(void);
-int drm_linux_acpi_notify(struct aml_node *, int, void *);
-
-/* Device setup support (drm_drv.c) */
-int drm_pciprobe(struct pci_attach_args *, const struct drm_pcidev * );
-struct drm_device *drm_attach_pci(struct drm_driver *,
- struct pci_attach_args *, int, int, struct device *, struct drm_device *);
-int drmprint(void *, const char *);
-int drmsubmatch(struct device *, void *, void *);
-dev_type_ioctl(drmioctl);
-dev_type_read(drmread);
-dev_type_poll(drmpoll);
-dev_type_open(drmopen);
-dev_type_close(drmclose);
-dev_type_mmap(drmmmap);
-struct drm_dmamem *drm_dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t,
- int, bus_size_t, int, int);
-void drm_dmamem_free(bus_dma_tag_t, struct drm_dmamem *);
-
-extern struct drm_dma_handle *drm_pci_alloc(struct drm_device *dev, size_t size,
- size_t align);
-extern void drm_pci_free(struct drm_device *dev, struct drm_dma_handle * dmah);
-
-const struct drm_pcidev *drm_find_description(int , int ,
- const struct drm_pcidev *);
-int drm_order(unsigned long);
-
-/* File operations helpers (drm_fops.c) */
-struct drm_file *drm_find_file_by_minor(struct drm_device *, int);
-struct drm_device *drm_get_device_from_kdev(dev_t);
-
-int drm_mtrr_add(unsigned long, size_t, int);
-int drm_mtrr_del(int, unsigned long, size_t, int);
-
-/* Cache management (drm_cache.c) */
-void drm_clflush_pages(struct vm_page *pages[], unsigned long num_pages);
-void drm_clflush_sg(struct sg_table *st);
-void drm_clflush_virt_range(void *addr, unsigned long length);
-
-/* AGP/PCI Express/GART support (drm_agpsupport.c) */
-struct drm_agp_head *drm_agp_init(void);
-void drm_agp_takedown(struct drm_device *);
-int drm_agp_acquire(struct drm_device *);
-int drm_agp_release(struct drm_device *);
-int drm_agp_info(struct drm_device *, struct drm_agp_info *);
-int drm_agp_enable(struct drm_device *, struct drm_agp_mode);
-void *drm_agp_allocate_memory(size_t, u32);
-int drm_agp_free_memory(void *);
-int drm_agp_bind_memory(void *, off_t);
-int drm_agp_unbind_memory(void *);
-int drm_agp_alloc(struct drm_device *, struct drm_agp_buffer *);
-int drm_agp_free(struct drm_device *, struct drm_agp_buffer *);
-int drm_agp_bind(struct drm_device *, struct drm_agp_binding *);
-int drm_agp_unbind(struct drm_device *, struct drm_agp_binding *);
-
-/* AGP/GART support (drm_agpsupport.c) */
-int drm_agp_acquire_ioctl(struct drm_device *, void *, struct drm_file *);
-int drm_agp_release_ioctl(struct drm_device *, void *, struct drm_file *);
-int drm_agp_enable_ioctl(struct drm_device *, void *, struct drm_file *);
-int drm_agp_info_ioctl(struct drm_device *, void *, struct drm_file *);
-int drm_agp_alloc_ioctl(struct drm_device *, void *, struct drm_file *);
-int drm_agp_free_ioctl(struct drm_device *, void *, struct drm_file *);
-int drm_agp_unbind_ioctl(struct drm_device *, void *, struct drm_file *);
-int drm_agp_bind_ioctl(struct drm_device *, void *, struct drm_file *);
-
-/* hotplug support */
-void drm_sysfs_hotplug_event(struct drm_device *);
-
-static inline int
-drm_sysfs_connector_add(struct drm_connector *connector)
-{
- return 0;
-}
-
-static inline void
-drm_sysfs_connector_remove(struct drm_connector *connector)
-{
-}
-
-/* helper for handling conditionals in various for_each macros */
-#define for_each_if(condition) if (!(condition)) {} else
-
-static inline bool
-drm_is_current_master(struct drm_file *file_priv)
-{
- return (file_priv->is_master == 1);
-}
-
-#endif /* __KERNEL__ */
-#endif /* _DRM_P_H_ */
diff --git a/sys/dev/pci/drm/include/drm/drm_agpsupport.h b/sys/dev/pci/drm/include/drm/drm_agpsupport.h
new file mode 100644
index 00000000000..77b2a58ae8f
--- /dev/null
+++ b/sys/dev/pci/drm/include/drm/drm_agpsupport.h
@@ -0,0 +1,47 @@
+/* Public domain. */
+
+#ifndef _DRM_AGPSUPPORT_H_
+#define _DRM_AGPSUPPORT_H_
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/agpvar.h>
+#include <uapi/drm/drm.h>
+
+struct drm_device;
+struct drm_file;
+
+struct drm_agp_head {
+ struct agp_softc *agpdev;
+ const char *chipset;
+ TAILQ_HEAD(agp_memlist, drm_agp_mem) memory;
+ struct agp_info info;
+ unsigned long base;
+ unsigned long mode;
+ unsigned long page_mask;
+ int acquired;
+ int cant_use_aperture;
+ int enabled;
+ int mtrr;
+};
+
+struct drm_agp_head *drm_agp_init(void);
+void drm_agp_takedown(struct drm_device *);
+int drm_agp_acquire(struct drm_device *);
+int drm_agp_release(struct drm_device *);
+int drm_agp_info(struct drm_device *, struct drm_agp_info *);
+int drm_agp_enable(struct drm_device *, struct drm_agp_mode);
+int drm_agp_alloc(struct drm_device *, struct drm_agp_buffer *);
+int drm_agp_free(struct drm_device *, struct drm_agp_buffer *);
+int drm_agp_bind(struct drm_device *, struct drm_agp_binding *);
+int drm_agp_unbind(struct drm_device *, struct drm_agp_binding *);
+
+int drm_agp_acquire_ioctl(struct drm_device *, void *, struct drm_file *);
+int drm_agp_release_ioctl(struct drm_device *, void *, struct drm_file *);
+int drm_agp_enable_ioctl(struct drm_device *, void *, struct drm_file *);
+int drm_agp_info_ioctl(struct drm_device *, void *, struct drm_file *);
+int drm_agp_alloc_ioctl(struct drm_device *, void *, struct drm_file *);
+int drm_agp_free_ioctl(struct drm_device *, void *, struct drm_file *);
+int drm_agp_unbind_ioctl(struct drm_device *, void *, struct drm_file *);
+int drm_agp_bind_ioctl(struct drm_device *, void *, struct drm_file *);
+
+#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_atomic.h b/sys/dev/pci/drm/include/drm/drm_atomic.h
index 1e713154f00..7b6cb4774e7 100644
--- a/sys/dev/pci/drm/include/drm/drm_atomic.h
+++ b/sys/dev/pci/drm/include/drm/drm_atomic.h
@@ -29,12 +29,13 @@
#define DRM_ATOMIC_H_
#include <drm/drm_crtc.h>
+#include <drm/drm_util.h>
/**
* struct drm_crtc_commit - track modeset commits on a CRTC
*
* This structure is used to track pending modeset changes and atomic commit on
- * a per-CRTC basis. Since updating the list should never block this structure
+ * a per-CRTC basis. Since updating the list should never block, this structure
* is reference counted to allow waiters to safely wait on an event to complete,
* without holding any locks.
*
@@ -59,8 +60,8 @@
* wait for flip_done <----
* clean up atomic state
*
- * The important bit to know is that cleanup_done is the terminal event, but the
- * ordering between flip_done and hw_done is entirely up to the specific driver
+ * The important bit to know is that &cleanup_done is the terminal event, but the
+ * ordering between &flip_done and &hw_done is entirely up to the specific driver
* and modeset state change.
*
* For an implementation of how to use this look at
@@ -91,6 +92,9 @@ struct drm_crtc_commit {
* commit is sent to userspace, or when an out-fence is singalled. Note
* that for most hardware, in most cases this happens after @hw_done is
* signalled.
+ *
+ * Completion of this stage is signalled implicitly by calling
+ * drm_crtc_send_vblank_event() on &drm_crtc_state.event.
*/
struct completion flip_done;
@@ -106,6 +110,9 @@ struct drm_crtc_commit {
* Note that this does not need to include separately reference-counted
* resources like backing storage buffer pinning, or runtime pm
* management.
+ *
+ * Drivers should call drm_atomic_helper_commit_hw_done() to signal
+ * completion of this stage.
*/
struct completion hw_done;
@@ -117,6 +124,9 @@ struct drm_crtc_commit {
* a vblank wait completed it might be a bit later. This completion is
* useful to throttle updates and avoid hardware updates getting ahead
* of the buffer cleanup too much.
+ *
+ * Drivers should call drm_atomic_helper_commit_cleanup_done() to signal
+ * completion of this stage.
*/
struct completion cleanup_done;
@@ -138,9 +148,9 @@ struct drm_crtc_commit {
/**
* @abort_completion:
*
- * A flag that's set after drm_atomic_helper_setup_commit takes a second
- * reference for the completion of $drm_crtc_state.event. It's used by
- * the free code to remove the second reference if commit fails.
+ * A flag that's set after drm_atomic_helper_setup_commit() takes a
+ * second reference for the completion of $drm_crtc_state.event. It's
+ * used by the free code to remove the second reference if commit fails.
*/
bool abort_completion;
};
@@ -191,7 +201,7 @@ struct drm_private_state;
* private objects. The structure itself is used as a vtable to identify the
* associated private object type. Each private object type that needs to be
* added to the atomic states is expected to have an implementation of these
- * hooks and pass a pointer to it's drm_private_state_funcs struct to
+ * hooks and pass a pointer to its drm_private_state_funcs struct to
* drm_atomic_get_private_obj_state().
*/
struct drm_private_state_funcs {
@@ -227,9 +237,31 @@ struct drm_private_state_funcs {
* Currently only tracks the state update functions and the opaque driver
* private state itself, but in the future might also track which
* &drm_modeset_lock is required to duplicate and update this object's state.
+ *
+ * All private objects must be initialized before the DRM device they are
+ * attached to is registered to the DRM subsystem (call to drm_dev_register())
+ * and should stay around until this DRM device is unregistered (call to
+ * drm_dev_unregister()). In other words, private objects lifetime is tied
+ * to the DRM device lifetime. This implies that:
+ *
+ * 1/ all calls to drm_atomic_private_obj_init() must be done before calling
+ * drm_dev_register()
+ * 2/ all calls to drm_atomic_private_obj_fini() must be done after calling
+ * drm_dev_unregister()
*/
struct drm_private_obj {
/**
+ * @head: List entry used to attach a private object to a &drm_device
+ * (queued to &drm_mode_config.privobj_list).
+ */
+ struct list_head head;
+
+ /**
+ * @lock: Modeset lock to protect the state object.
+ */
+ struct drm_modeset_lock lock;
+
+ /**
* @state: Current atomic state for this driver private object.
*/
struct drm_private_state *state;
@@ -244,6 +276,18 @@ struct drm_private_obj {
};
/**
+ * drm_for_each_privobj() - private object iterator
+ *
+ * @privobj: pointer to the current private object. Updated after each
+ * iteration
+ * @dev: the DRM device we want get private objects from
+ *
+ * Allows one to iterate over all private objects attached to @dev
+ */
+#define drm_for_each_privobj(privobj, dev) \
+ list_for_each_entry(privobj, &(dev)->mode_config.privobj_list, head)
+
+/**
* struct drm_private_state - base struct for driver private object state
* @state: backpointer to global drm_atomic_state
*
@@ -264,7 +308,6 @@ struct __drm_private_objs_state {
* struct drm_atomic_state - the global state object for atomic updates
* @ref: count of all references to this state (will not be freed until zero)
* @dev: parent DRM device
- * @allow_modeset: allow full modeset
* @legacy_cursor_update: hint to enforce legacy cursor IOCTL semantics
* @async_update: hint for asynchronous plane update
* @planes: pointer to array of structures with per-plane data
@@ -283,9 +326,27 @@ struct drm_atomic_state {
struct kref ref;
struct drm_device *dev;
+
+ /**
+ * @allow_modeset:
+ *
+ * Allow full modeset. This is used by the ATOMIC IOCTL handler to
+ * implement the DRM_MODE_ATOMIC_ALLOW_MODESET flag. Drivers should
+ * never consult this flag, instead looking at the output of
+ * drm_atomic_crtc_needs_modeset().
+ */
bool allow_modeset : 1;
bool legacy_cursor_update : 1;
bool async_update : 1;
+ /**
+ * @duplicated:
+ *
+ * Indicates whether or not this atomic state was duplicated using
+ * drm_atomic_helper_duplicate_state(). Drivers and atomic helpers
+ * should use this to fixup normal inconsistencies in duplicated
+ * states.
+ */
+ bool duplicated : 1;
struct __drm_planes_state *planes;
struct __drm_crtcs_state *crtcs;
int num_connector;
@@ -302,7 +363,7 @@ struct drm_atomic_state {
* When a connector or plane is not bound to any CRTC, it's still important
* to preserve linearity to prevent the atomic states from being freed to early.
*
- * This commit (if set) is not bound to any crtc, but will be completed when
+ * This commit (if set) is not bound to any CRTC, but will be completed when
* drm_atomic_helper_commit_hw_done() is called.
*/
struct drm_crtc_commit *fake_commit;
@@ -384,9 +445,6 @@ void drm_atomic_state_default_release(struct drm_atomic_state *state);
struct drm_crtc_state * __must_check
drm_atomic_get_crtc_state(struct drm_atomic_state *state,
struct drm_crtc *crtc);
-int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
- struct drm_crtc_state *state, struct drm_property *property,
- uint64_t val);
struct drm_plane_state * __must_check
drm_atomic_get_plane_state(struct drm_atomic_state *state,
struct drm_plane *plane);
@@ -394,7 +452,8 @@ struct drm_connector_state * __must_check
drm_atomic_get_connector_state(struct drm_atomic_state *state,
struct drm_connector *connector);
-void drm_atomic_private_obj_init(struct drm_private_obj *obj,
+void drm_atomic_private_obj_init(struct drm_device *dev,
+ struct drm_private_obj *obj,
struct drm_private_state *state,
const struct drm_private_state_funcs *funcs);
void drm_atomic_private_obj_fini(struct drm_private_obj *obj);
@@ -402,14 +461,27 @@ void drm_atomic_private_obj_fini(struct drm_private_obj *obj);
struct drm_private_state * __must_check
drm_atomic_get_private_obj_state(struct drm_atomic_state *state,
struct drm_private_obj *obj);
+struct drm_private_state *
+drm_atomic_get_old_private_obj_state(struct drm_atomic_state *state,
+ struct drm_private_obj *obj);
+struct drm_private_state *
+drm_atomic_get_new_private_obj_state(struct drm_atomic_state *state,
+ struct drm_private_obj *obj);
+
+struct drm_connector *
+drm_atomic_get_old_connector_for_encoder(struct drm_atomic_state *state,
+ struct drm_encoder *encoder);
+struct drm_connector *
+drm_atomic_get_new_connector_for_encoder(struct drm_atomic_state *state,
+ struct drm_encoder *encoder);
/**
- * drm_atomic_get_existing_crtc_state - get crtc state, if it exists
+ * drm_atomic_get_existing_crtc_state - get CRTC state, if it exists
* @state: global atomic state object
- * @crtc: crtc to grab
+ * @crtc: CRTC to grab
*
- * This function returns the crtc state for the given crtc, or NULL
- * if the crtc is not part of the global atomic state.
+ * This function returns the CRTC state for the given CRTC, or NULL
+ * if the CRTC is not part of the global atomic state.
*
* This function is deprecated, @drm_atomic_get_old_crtc_state or
* @drm_atomic_get_new_crtc_state should be used instead.
@@ -422,12 +494,12 @@ drm_atomic_get_existing_crtc_state(struct drm_atomic_state *state,
}
/**
- * drm_atomic_get_old_crtc_state - get old crtc state, if it exists
+ * drm_atomic_get_old_crtc_state - get old CRTC state, if it exists
* @state: global atomic state object
- * @crtc: crtc to grab
+ * @crtc: CRTC to grab
*
- * This function returns the old crtc state for the given crtc, or
- * NULL if the crtc is not part of the global atomic state.
+ * This function returns the old CRTC state for the given CRTC, or
+ * NULL if the CRTC is not part of the global atomic state.
*/
static inline struct drm_crtc_state *
drm_atomic_get_old_crtc_state(struct drm_atomic_state *state,
@@ -436,12 +508,12 @@ drm_atomic_get_old_crtc_state(struct drm_atomic_state *state,
return state->crtcs[drm_crtc_index(crtc)].old_state;
}
/**
- * drm_atomic_get_new_crtc_state - get new crtc state, if it exists
+ * drm_atomic_get_new_crtc_state - get new CRTC state, if it exists
* @state: global atomic state object
- * @crtc: crtc to grab
+ * @crtc: CRTC to grab
*
- * This function returns the new crtc state for the given crtc, or
- * NULL if the crtc is not part of the global atomic state.
+ * This function returns the new CRTC state for the given CRTC, or
+ * NULL if the CRTC is not part of the global atomic state.
*/
static inline struct drm_crtc_state *
drm_atomic_get_new_crtc_state(struct drm_atomic_state *state,
@@ -598,24 +670,8 @@ __drm_atomic_get_current_plane_state(struct drm_atomic_state *state,
}
int __must_check
-drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
- const struct drm_display_mode *mode);
-int __must_check
-drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
- struct drm_property_blob *blob);
-int __must_check
-drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
- struct drm_crtc *crtc);
-void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
- struct drm_framebuffer *fb);
-void drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
- struct dma_fence *fence);
-int __must_check
-drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
- struct drm_crtc *crtc);
-int drm_atomic_set_writeback_fb_for_connector(
- struct drm_connector_state *conn_state,
- struct drm_framebuffer *fb);
+drm_atomic_add_encoder_bridges(struct drm_atomic_state *state,
+ struct drm_encoder *encoder);
int __must_check
drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
struct drm_crtc *crtc);
@@ -649,6 +705,7 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
(__i)++) \
for_each_if ((__state)->connectors[__i].ptr && \
((connector) = (__state)->connectors[__i].ptr, \
+ (void)(connector) /* Only to avoid unused-but-set-variable warning */, \
(old_connector_state) = (__state)->connectors[__i].old_state, \
(new_connector_state) = (__state)->connectors[__i].new_state, 1))
@@ -670,6 +727,7 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
(__i)++) \
for_each_if ((__state)->connectors[__i].ptr && \
((connector) = (__state)->connectors[__i].ptr, \
+ (void)(connector) /* Only to avoid unused-but-set-variable warning */, \
(old_connector_state) = (__state)->connectors[__i].old_state, 1))
/**
@@ -690,7 +748,9 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
(__i)++) \
for_each_if ((__state)->connectors[__i].ptr && \
((connector) = (__state)->connectors[__i].ptr, \
- (new_connector_state) = (__state)->connectors[__i].new_state, 1))
+ (void)(connector) /* Only to avoid unused-but-set-variable warning */, \
+ (new_connector_state) = (__state)->connectors[__i].new_state, \
+ (void)(new_connector_state) /* Only to avoid unused-but-set-variable warning */, 1))
/**
* for_each_oldnew_crtc_in_state - iterate over all CRTCs in an atomic update
@@ -710,7 +770,9 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
(__i)++) \
for_each_if ((__state)->crtcs[__i].ptr && \
((crtc) = (__state)->crtcs[__i].ptr, \
+ (void)(crtc) /* Only to avoid unused-but-set-variable warning */, \
(old_crtc_state) = (__state)->crtcs[__i].old_state, \
+ (void)(old_crtc_state) /* Only to avoid unused-but-set-variable warning */, \
(new_crtc_state) = (__state)->crtcs[__i].new_state, 1))
/**
@@ -749,7 +811,9 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
(__i)++) \
for_each_if ((__state)->crtcs[__i].ptr && \
((crtc) = (__state)->crtcs[__i].ptr, \
- (new_crtc_state) = (__state)->crtcs[__i].new_state, 1))
+ (void)(crtc) /* Only to avoid unused-but-set-variable warning */, \
+ (new_crtc_state) = (__state)->crtcs[__i].new_state, \
+ (void)(new_crtc_state) /* Only to avoid unused-but-set-variable warning */, 1))
/**
* for_each_oldnew_plane_in_state - iterate over all planes in an atomic update
@@ -769,6 +833,7 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
(__i)++) \
for_each_if ((__state)->planes[__i].ptr && \
((plane) = (__state)->planes[__i].ptr, \
+ (void)(plane) /* Only to avoid unused-but-set-variable warning */, \
(old_plane_state) = (__state)->planes[__i].old_state,\
(new_plane_state) = (__state)->planes[__i].new_state, 1))
@@ -829,7 +894,9 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
(__i)++) \
for_each_if ((__state)->planes[__i].ptr && \
((plane) = (__state)->planes[__i].ptr, \
- (new_plane_state) = (__state)->planes[__i].new_state, 1))
+ (void)(plane) /* Only to avoid unused-but-set-variable warning */, \
+ (new_plane_state) = (__state)->planes[__i].new_state, \
+ (void)(new_plane_state) /* Only to avoid unused-but-set-variable warning */, 1))
/**
* for_each_oldnew_private_obj_in_state - iterate over all private objects in an atomic update
@@ -913,4 +980,92 @@ drm_atomic_crtc_needs_modeset(const struct drm_crtc_state *state)
state->connectors_changed;
}
+/**
+ * drm_atomic_crtc_effectively_active - compute whether CRTC is actually active
+ * @state: &drm_crtc_state for the CRTC
+ *
+ * When in self refresh mode, the crtc_state->active value will be false, since
+ * the CRTC is off. However in some cases we're interested in whether the CRTC
+ * is active, or effectively active (ie: it's connected to an active display).
+ * In these cases, use this function instead of just checking active.
+ */
+static inline bool
+drm_atomic_crtc_effectively_active(const struct drm_crtc_state *state)
+{
+ return state->active || state->self_refresh_active;
+}
+
+/**
+ * struct drm_bus_cfg - bus configuration
+ *
+ * This structure stores the configuration of a physical bus between two
+ * components in an output pipeline, usually between two bridges, an encoder
+ * and a bridge, or a bridge and a connector.
+ *
+ * The bus configuration is stored in &drm_bridge_state separately for the
+ * input and output buses, as seen from the point of view of each bridge. The
+ * bus configuration of a bridge output is usually identical to the
+ * configuration of the next bridge's input, but may differ if the signals are
+ * modified between the two bridges, for instance by an inverter on the board.
+ * The input and output configurations of a bridge may differ if the bridge
+ * modifies the signals internally, for instance by performing format
+ * conversion, or modifying signals polarities.
+ */
+struct drm_bus_cfg {
+ /**
+ * @format: format used on this bus (one of the MEDIA_BUS_FMT_* format)
+ *
+ * This field should not be directly modified by drivers
+ * (drm_atomic_bridge_chain_select_bus_fmts() takes care of the bus
+ * format negotiation).
+ */
+ u32 format;
+
+ /**
+ * @flags: DRM_BUS_* flags used on this bus
+ */
+ u32 flags;
+};
+
+/**
+ * struct drm_bridge_state - Atomic bridge state object
+ */
+struct drm_bridge_state {
+ /**
+ * @base: inherit from &drm_private_state
+ */
+ struct drm_private_state base;
+
+ /**
+ * @bridge: the bridge this state refers to
+ */
+ struct drm_bridge *bridge;
+
+ /**
+ * @input_bus_cfg: input bus configuration
+ */
+ struct drm_bus_cfg input_bus_cfg;
+
+ /**
+ * @output_bus_cfg: input bus configuration
+ */
+ struct drm_bus_cfg output_bus_cfg;
+};
+
+static inline struct drm_bridge_state *
+drm_priv_to_bridge_state(struct drm_private_state *priv)
+{
+ return container_of(priv, struct drm_bridge_state, base);
+}
+
+struct drm_bridge_state *
+drm_atomic_get_bridge_state(struct drm_atomic_state *state,
+ struct drm_bridge *bridge);
+struct drm_bridge_state *
+drm_atomic_get_old_bridge_state(struct drm_atomic_state *state,
+ struct drm_bridge *bridge);
+struct drm_bridge_state *
+drm_atomic_get_new_bridge_state(struct drm_atomic_state *state,
+ struct drm_bridge *bridge);
+
#endif /* DRM_ATOMIC_H_ */
diff --git a/sys/dev/pci/drm/include/drm/drm_atomic_helper.h b/sys/dev/pci/drm/include/drm/drm_atomic_helper.h
index 99e2a5297c6..b268180c97e 100644
--- a/sys/dev/pci/drm/include/drm/drm_atomic_helper.h
+++ b/sys/dev/pci/drm/include/drm/drm_atomic_helper.h
@@ -31,6 +31,8 @@
#include <drm/drm_crtc.h>
#include <drm/drm_modeset_helper_vtables.h>
#include <drm/drm_modeset_helper.h>
+#include <drm/drm_atomic_state_helper.h>
+#include <drm/drm_util.h>
struct drm_atomic_state;
struct drm_private_obj;
@@ -115,16 +117,15 @@ int drm_atomic_helper_update_plane(struct drm_plane *plane,
struct drm_modeset_acquire_ctx *ctx);
int drm_atomic_helper_disable_plane(struct drm_plane *plane,
struct drm_modeset_acquire_ctx *ctx);
-int __drm_atomic_helper_disable_plane(struct drm_plane *plane,
- struct drm_plane_state *plane_state);
int drm_atomic_helper_set_config(struct drm_mode_set *set,
struct drm_modeset_acquire_ctx *ctx);
-int __drm_atomic_helper_set_config(struct drm_mode_set *set,
- struct drm_atomic_state *state);
int drm_atomic_helper_disable_all(struct drm_device *dev,
struct drm_modeset_acquire_ctx *ctx);
void drm_atomic_helper_shutdown(struct drm_device *dev);
+struct drm_atomic_state *
+drm_atomic_helper_duplicate_state(struct drm_device *dev,
+ struct drm_modeset_acquire_ctx *ctx);
struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev);
int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state,
struct drm_modeset_acquire_ctx *ctx);
@@ -143,54 +144,15 @@ int drm_atomic_helper_page_flip_target(
uint32_t flags,
uint32_t target,
struct drm_modeset_acquire_ctx *ctx);
-struct drm_encoder *
-drm_atomic_helper_best_encoder(struct drm_connector *connector);
-
-/* default implementations for state handling */
-void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc);
-void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
- struct drm_crtc_state *state);
-struct drm_crtc_state *
-drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc);
-void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state);
-void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
- struct drm_crtc_state *state);
-
-void drm_atomic_helper_plane_reset(struct drm_plane *plane);
-void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
- struct drm_plane_state *state);
-struct drm_plane_state *
-drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane);
-void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state);
-void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
- struct drm_plane_state *state);
-
-void __drm_atomic_helper_connector_reset(struct drm_connector *connector,
- struct drm_connector_state *conn_state);
-void drm_atomic_helper_connector_reset(struct drm_connector *connector);
-void
-__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
- struct drm_connector_state *state);
-struct drm_connector_state *
-drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector);
-struct drm_atomic_state *
-drm_atomic_helper_duplicate_state(struct drm_device *dev,
- struct drm_modeset_acquire_ctx *ctx);
-void
-__drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state);
-void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
- struct drm_connector_state *state);
int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
u16 *red, u16 *green, u16 *blue,
uint32_t size,
struct drm_modeset_acquire_ctx *ctx);
-void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj,
- struct drm_private_state *state);
/**
* drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC
* @plane: the loop cursor
- * @crtc: the crtc whose planes are iterated
+ * @crtc: the CRTC whose planes are iterated
*
* This iterates over the current state, useful (for example) when applying
* atomic state after it has been checked and swapped. To iterate over the
@@ -204,7 +166,7 @@ void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj
/**
* drm_crtc_atomic_state_for_each_plane - iterate over attached planes in new state
* @plane: the loop cursor
- * @crtc_state: the incoming crtc-state
+ * @crtc_state: the incoming CRTC state
*
* Similar to drm_crtc_for_each_plane(), but iterates the planes that will be
* attached if the specified state is applied. Useful during for example
@@ -218,7 +180,7 @@ void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj
* drm_crtc_atomic_state_for_each_plane_state - iterate over attached planes in new state
* @plane: the loop cursor
* @plane_state: loop cursor for the plane's state, must be const
- * @crtc_state: the incoming crtc-state
+ * @crtc_state: the incoming CRTC state
*
* Similar to drm_crtc_for_each_plane(), but iterates the planes that will be
* attached if the specified state is applied. Useful during for example
@@ -227,7 +189,7 @@ void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj
*
* Compared to just drm_atomic_crtc_state_for_each_plane() this also fills in a
* const plane_state. This is useful when a driver just wants to peek at other
- * active planes on this crtc, but does not need to change it.
+ * active planes on this CRTC, but does not need to change it.
*/
#define drm_atomic_crtc_state_for_each_plane_state(plane, plane_state, crtc_state) \
drm_for_each_plane_mask(plane, (crtc_state)->state->dev, (crtc_state)->plane_mask) \
@@ -262,4 +224,12 @@ drm_atomic_plane_disabling(struct drm_plane_state *old_plane_state,
return old_plane_state->crtc && !new_plane_state->crtc;
}
+u32 *
+drm_atomic_helper_bridge_propagate_bus_fmt(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state,
+ u32 output_fmt,
+ unsigned int *num_input_fmts);
+
#endif /* DRM_ATOMIC_HELPER_H_ */
diff --git a/sys/dev/pci/drm/include/drm/drm_atomic_state_helper.h b/sys/dev/pci/drm/include/drm/drm_atomic_state_helper.h
new file mode 100644
index 00000000000..3f8f1d627f7
--- /dev/null
+++ b/sys/dev/pci/drm/include/drm/drm_atomic_state_helper.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2018 Intel Corp.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Rob Clark <robdclark@gmail.com>
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ */
+
+#include <linux/types.h>
+
+struct drm_bridge;
+struct drm_bridge_state;
+struct drm_crtc;
+struct drm_crtc_state;
+struct drm_plane;
+struct drm_plane_state;
+struct drm_connector;
+struct drm_connector_state;
+struct drm_private_obj;
+struct drm_private_state;
+struct drm_modeset_acquire_ctx;
+struct drm_device;
+
+void __drm_atomic_helper_crtc_state_reset(struct drm_crtc_state *state,
+ struct drm_crtc *crtc);
+void __drm_atomic_helper_crtc_reset(struct drm_crtc *crtc,
+ struct drm_crtc_state *state);
+void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc);
+void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
+ struct drm_crtc_state *state);
+struct drm_crtc_state *
+drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc);
+void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state);
+void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
+ struct drm_crtc_state *state);
+
+void __drm_atomic_helper_plane_state_reset(struct drm_plane_state *state,
+ struct drm_plane *plane);
+void __drm_atomic_helper_plane_reset(struct drm_plane *plane,
+ struct drm_plane_state *state);
+void drm_atomic_helper_plane_reset(struct drm_plane *plane);
+void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
+ struct drm_plane_state *state);
+struct drm_plane_state *
+drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane);
+void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state);
+void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
+ struct drm_plane_state *state);
+
+void __drm_atomic_helper_connector_state_reset(struct drm_connector_state *conn_state,
+ struct drm_connector *connector);
+void __drm_atomic_helper_connector_reset(struct drm_connector *connector,
+ struct drm_connector_state *conn_state);
+void drm_atomic_helper_connector_reset(struct drm_connector *connector);
+void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector);
+void
+__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
+ struct drm_connector_state *state);
+struct drm_connector_state *
+drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector);
+void
+__drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state);
+void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
+ struct drm_connector_state *state);
+void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj,
+ struct drm_private_state *state);
+
+void __drm_atomic_helper_bridge_duplicate_state(struct drm_bridge *bridge,
+ struct drm_bridge_state *state);
+struct drm_bridge_state *
+drm_atomic_helper_bridge_duplicate_state(struct drm_bridge *bridge);
+void drm_atomic_helper_bridge_destroy_state(struct drm_bridge *bridge,
+ struct drm_bridge_state *state);
+void __drm_atomic_helper_bridge_reset(struct drm_bridge *bridge,
+ struct drm_bridge_state *state);
+struct drm_bridge_state *
+drm_atomic_helper_bridge_reset(struct drm_bridge *bridge);
diff --git a/sys/dev/pci/drm/include/drm/drm_atomic_uapi.h b/sys/dev/pci/drm/include/drm/drm_atomic_uapi.h
new file mode 100644
index 00000000000..8cec52ad127
--- /dev/null
+++ b/sys/dev/pci/drm/include/drm/drm_atomic_uapi.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2014 Red Hat
+ * Copyright (C) 2014 Intel Corp.
+ * Copyright (C) 2018 Intel Corp.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Rob Clark <robdclark@gmail.com>
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ */
+
+#ifndef DRM_ATOMIC_UAPI_H_
+#define DRM_ATOMIC_UAPI_H_
+
+struct drm_crtc_state;
+struct drm_display_mode;
+struct drm_property_blob;
+struct drm_plane_state;
+struct drm_crtc;
+struct drm_connector_state;
+struct dma_fence;
+struct drm_framebuffer;
+
+int __must_check
+drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
+ const struct drm_display_mode *mode);
+int __must_check
+drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
+ struct drm_property_blob *blob);
+int __must_check
+drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
+ struct drm_crtc *crtc);
+void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
+ struct drm_framebuffer *fb);
+void drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
+ struct dma_fence *fence);
+int __must_check
+drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
+ struct drm_crtc *crtc);
+
+#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_audio_component.h b/sys/dev/pci/drm/include/drm/drm_audio_component.h
index 4923b00328c..a45f9348703 100644
--- a/sys/dev/pci/drm/include/drm/drm_audio_component.h
+++ b/sys/dev/pci/drm/include/drm/drm_audio_component.h
@@ -5,6 +5,7 @@
#define _DRM_AUDIO_COMPONENT_H_
struct drm_audio_component;
+struct device;
/**
* struct drm_audio_component_ops - Ops implemented by DRM driver, called by hda driver
@@ -18,14 +19,17 @@ struct drm_audio_component_ops {
* @get_power: get the POWER_DOMAIN_AUDIO power well
*
* Request the power well to be turned on.
+ *
+ * Returns a wakeref cookie to be passed back to the corresponding
+ * call to @put_power.
*/
- void (*get_power)(struct device *);
+ unsigned long (*get_power)(struct device *);
/**
* @put_power: put the POWER_DOMAIN_AUDIO power well
*
* Allow the power well to be turned off.
*/
- void (*put_power)(struct device *);
+ void (*put_power)(struct device *, unsigned long);
/**
* @codec_wake_override: Enable/disable codec wake signal
*/
diff --git a/sys/dev/pci/drm/include/drm/drm_auth.h b/sys/dev/pci/drm/include/drm/drm_auth.h
new file mode 100644
index 00000000000..6bf8b2b7899
--- /dev/null
+++ b/sys/dev/pci/drm/include/drm/drm_auth.h
@@ -0,0 +1,115 @@
+#ifndef _DRM_AUTH_H_
+#define _DRM_AUTH_H_
+
+/*
+ * Internal Header for the Direct Rendering Manager
+ *
+ * Copyright 2016 Intel Corporation
+ *
+ * Author: Daniel Vetter <daniel.vetter@ffwll.ch>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <linux/idr.h>
+#include <linux/kref.h>
+#include <linux/wait.h>
+
+struct drm_file;
+struct drm_hw_lock;
+
+/*
+ * Legacy DRI1 locking data structure. Only here instead of in drm_legacy.h for
+ * include ordering reasons.
+ *
+ * DO NOT USE.
+ */
+struct drm_lock_data {
+ struct drm_hw_lock *hw_lock;
+ struct drm_file *file_priv;
+ wait_queue_head_t lock_queue;
+ unsigned long lock_time;
+ spinlock_t spinlock;
+ uint32_t kernel_waiters;
+ uint32_t user_waiters;
+ int idle_has_lock;
+};
+
+/**
+ * struct drm_master - drm master structure
+ *
+ * @refcount: Refcount for this master object.
+ * @dev: Link back to the DRM device
+ * @driver_priv: Pointer to driver-private information.
+ * @lessor: Lease holder
+ * @lessee_id: id for lessees. Owners always have id 0
+ * @lessee_list: other lessees of the same master
+ * @lessees: drm_masters leasing from this one
+ * @leases: Objects leased to this drm_master.
+ * @lessee_idr: All lessees under this owner (only used where lessor == NULL)
+ *
+ * Note that master structures are only relevant for the legacy/primary device
+ * nodes, hence there can only be one per device, not one per drm_minor.
+ */
+struct drm_master {
+ struct kref refcount;
+ struct drm_device *dev;
+ /**
+ * @unique: Unique identifier: e.g. busid. Protected by
+ * &drm_device.master_mutex.
+ */
+ char *unique;
+ /**
+ * @unique_len: Length of unique field. Protected by
+ * &drm_device.master_mutex.
+ */
+ int unique_len;
+ /**
+ * @magic_map: Map of used authentication tokens. Protected by
+ * &drm_device.master_mutex.
+ */
+ struct idr magic_map;
+ void *driver_priv;
+
+ /* Tree of display resource leases, each of which is a drm_master struct
+ * All of these get activated simultaneously, so drm_device master points
+ * at the top of the tree (for which lessor is NULL). Protected by
+ * &drm_device.mode_config.idr_mutex.
+ */
+
+ struct drm_master *lessor;
+ int lessee_id;
+ struct list_head lessee_list;
+ struct list_head lessees;
+ struct idr leases;
+ struct idr lessee_idr;
+ /* private: */
+#if IS_ENABLED(CONFIG_DRM_LEGACY)
+ struct drm_lock_data lock;
+#endif
+};
+
+struct drm_master *drm_master_get(struct drm_master *master);
+void drm_master_put(struct drm_master **master);
+bool drm_is_current_master(struct drm_file *fpriv);
+
+struct drm_master *drm_master_create(struct drm_device *dev);
+
+#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_blend.h b/sys/dev/pci/drm/include/drm/drm_blend.h
index 330c561c4c1..88bdfec3bd8 100644
--- a/sys/dev/pci/drm/include/drm/drm_blend.h
+++ b/sys/dev/pci/drm/include/drm/drm_blend.h
@@ -27,6 +27,10 @@
#include <linux/ctype.h>
#include <drm/drm_mode.h>
+#define DRM_MODE_BLEND_PREMULTI 0
+#define DRM_MODE_BLEND_COVERAGE 1
+#define DRM_MODE_BLEND_PIXEL_NONE 2
+
struct drm_device;
struct drm_atomic_state;
struct drm_plane;
@@ -52,4 +56,6 @@ int drm_plane_create_zpos_immutable_property(struct drm_plane *plane,
unsigned int zpos);
int drm_atomic_normalize_zpos(struct drm_device *dev,
struct drm_atomic_state *state);
+int drm_plane_create_blend_mode_property(struct drm_plane *plane,
+ unsigned int supported_modes);
#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_bridge.h b/sys/dev/pci/drm/include/drm/drm_bridge.h
index bd850747ce5..20e0a0d6d7c 100644
--- a/sys/dev/pci/drm/include/drm/drm_bridge.h
+++ b/sys/dev/pci/drm/include/drm/drm_bridge.h
@@ -23,14 +23,32 @@
#ifndef __DRM_BRIDGE_H__
#define __DRM_BRIDGE_H__
-#include <linux/list.h>
#include <linux/ctype.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_encoder.h>
#include <drm/drm_mode_object.h>
#include <drm/drm_modes.h>
struct drm_bridge;
struct drm_bridge_timings;
+struct drm_connector;
struct drm_panel;
+struct edid;
+struct i2c_adapter;
+
+/**
+ * enum drm_bridge_attach_flags - Flags for &drm_bridge_funcs.attach
+ */
+enum drm_bridge_attach_flags {
+ /**
+ * @DRM_BRIDGE_ATTACH_NO_CONNECTOR: When this flag is set the bridge
+ * shall not create a drm_connector.
+ */
+ DRM_BRIDGE_ATTACH_NO_CONNECTOR = BIT(0),
+};
/**
* struct drm_bridge_funcs - drm_bridge control functions
@@ -40,15 +58,17 @@ struct drm_bridge_funcs {
* @attach:
*
* This callback is invoked whenever our bridge is being attached to a
- * &drm_encoder.
+ * &drm_encoder. The flags argument tunes the behaviour of the attach
+ * operation (see DRM_BRIDGE_ATTACH_*).
*
- * The attach callback is optional.
+ * The @attach callback is optional.
*
* RETURNS:
*
* Zero on success, error code on failure.
*/
- int (*attach)(struct drm_bridge *bridge);
+ int (*attach)(struct drm_bridge *bridge,
+ enum drm_bridge_attach_flags flags);
/**
* @detach:
@@ -56,7 +76,7 @@ struct drm_bridge_funcs {
* This callback is invoked whenever our bridge is being detached from a
* &drm_encoder.
*
- * The detach callback is optional.
+ * The @detach callback is optional.
*/
void (*detach)(struct drm_bridge *bridge);
@@ -76,7 +96,7 @@ struct drm_bridge_funcs {
* atomic helpers to validate modes supplied by userspace in
* drm_atomic_helper_check_modeset().
*
- * This function is optional.
+ * The @mode_valid callback is optional.
*
* NOTE:
*
@@ -108,7 +128,9 @@ struct drm_bridge_funcs {
* this function passes all other callbacks must succeed for this
* configuration.
*
- * The mode_fixup callback is optional.
+ * The mode_fixup callback is optional. &drm_bridge_funcs.mode_fixup()
+ * is not called when &drm_bridge_funcs.atomic_check() is implemented,
+ * so only one of them should be provided.
*
* NOTE:
*
@@ -146,7 +168,7 @@ struct drm_bridge_funcs {
* The bridge can assume that the display pipe (i.e. clocks and timing
* signals) feeding it is still running when this callback is called.
*
- * The disable callback is optional.
+ * The @disable callback is optional.
*/
void (*disable)(struct drm_bridge *bridge);
@@ -165,7 +187,7 @@ struct drm_bridge_funcs {
* singals) feeding it is no longer running when this callback is
* called.
*
- * The post_disable callback is optional.
+ * The @post_disable callback is optional.
*/
void (*post_disable)(struct drm_bridge *bridge);
@@ -196,8 +218,8 @@ struct drm_bridge_funcs {
* the DRM framework will have to be extended with DRM bridge states.
*/
void (*mode_set)(struct drm_bridge *bridge,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode);
+ const struct drm_display_mode *mode,
+ const struct drm_display_mode *adjusted_mode);
/**
* @pre_enable:
*
@@ -214,7 +236,7 @@ struct drm_bridge_funcs {
* not enable the display link feeding the next bridge in the chain (if
* there is one) when this callback is called.
*
- * The pre_enable callback is optional.
+ * The @pre_enable callback is optional.
*/
void (*pre_enable)(struct drm_bridge *bridge);
@@ -234,9 +256,377 @@ struct drm_bridge_funcs {
* callback must enable the display link feeding the next bridge in the
* chain if there is one.
*
- * The enable callback is optional.
+ * The @enable callback is optional.
*/
void (*enable)(struct drm_bridge *bridge);
+
+ /**
+ * @atomic_pre_enable:
+ *
+ * This callback should enable the bridge. It is called right before
+ * the preceding element in the display pipe is enabled. If the
+ * preceding element is a bridge this means it's called before that
+ * bridge's @atomic_pre_enable or @pre_enable function. If the preceding
+ * element is a &drm_encoder it's called right before the encoder's
+ * &drm_encoder_helper_funcs.atomic_enable hook.
+ *
+ * The display pipe (i.e. clocks and timing signals) feeding this bridge
+ * will not yet be running when this callback is called. The bridge must
+ * not enable the display link feeding the next bridge in the chain (if
+ * there is one) when this callback is called.
+ *
+ * Note that this function will only be invoked in the context of an
+ * atomic commit. It will not be invoked from
+ * &drm_bridge_chain_pre_enable. It would be prudent to also provide an
+ * implementation of @pre_enable if you are expecting driver calls into
+ * &drm_bridge_chain_pre_enable.
+ *
+ * The @atomic_pre_enable callback is optional.
+ */
+ void (*atomic_pre_enable)(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state);
+
+ /**
+ * @atomic_enable:
+ *
+ * This callback should enable the bridge. It is called right after
+ * the preceding element in the display pipe is enabled. If the
+ * preceding element is a bridge this means it's called after that
+ * bridge's @atomic_enable or @enable function. If the preceding element
+ * is a &drm_encoder it's called right after the encoder's
+ * &drm_encoder_helper_funcs.atomic_enable hook.
+ *
+ * The bridge can assume that the display pipe (i.e. clocks and timing
+ * signals) feeding it is running when this callback is called. This
+ * callback must enable the display link feeding the next bridge in the
+ * chain if there is one.
+ *
+ * Note that this function will only be invoked in the context of an
+ * atomic commit. It will not be invoked from &drm_bridge_chain_enable.
+ * It would be prudent to also provide an implementation of @enable if
+ * you are expecting driver calls into &drm_bridge_chain_enable.
+ *
+ * The @atomic_enable callback is optional.
+ */
+ void (*atomic_enable)(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state);
+ /**
+ * @atomic_disable:
+ *
+ * This callback should disable the bridge. It is called right before
+ * the preceding element in the display pipe is disabled. If the
+ * preceding element is a bridge this means it's called before that
+ * bridge's @atomic_disable or @disable vfunc. If the preceding element
+ * is a &drm_encoder it's called right before the
+ * &drm_encoder_helper_funcs.atomic_disable hook.
+ *
+ * The bridge can assume that the display pipe (i.e. clocks and timing
+ * signals) feeding it is still running when this callback is called.
+ *
+ * Note that this function will only be invoked in the context of an
+ * atomic commit. It will not be invoked from
+ * &drm_bridge_chain_disable. It would be prudent to also provide an
+ * implementation of @disable if you are expecting driver calls into
+ * &drm_bridge_chain_disable.
+ *
+ * The @atomic_disable callback is optional.
+ */
+ void (*atomic_disable)(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state);
+
+ /**
+ * @atomic_post_disable:
+ *
+ * This callback should disable the bridge. It is called right after the
+ * preceding element in the display pipe is disabled. If the preceding
+ * element is a bridge this means it's called after that bridge's
+ * @atomic_post_disable or @post_disable function. If the preceding
+ * element is a &drm_encoder it's called right after the encoder's
+ * &drm_encoder_helper_funcs.atomic_disable hook.
+ *
+ * The bridge must assume that the display pipe (i.e. clocks and timing
+ * signals) feeding it is no longer running when this callback is
+ * called.
+ *
+ * Note that this function will only be invoked in the context of an
+ * atomic commit. It will not be invoked from
+ * &drm_bridge_chain_post_disable.
+ * It would be prudent to also provide an implementation of
+ * @post_disable if you are expecting driver calls into
+ * &drm_bridge_chain_post_disable.
+ *
+ * The @atomic_post_disable callback is optional.
+ */
+ void (*atomic_post_disable)(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state);
+
+ /**
+ * @atomic_duplicate_state:
+ *
+ * Duplicate the current bridge state object (which is guaranteed to be
+ * non-NULL).
+ *
+ * The atomic_duplicate_state hook is mandatory if the bridge
+ * implements any of the atomic hooks, and should be left unassigned
+ * otherwise. For bridges that don't subclass &drm_bridge_state, the
+ * drm_atomic_helper_bridge_duplicate_state() helper function shall be
+ * used to implement this hook.
+ *
+ * RETURNS:
+ * A valid drm_bridge_state object or NULL if the allocation fails.
+ */
+ struct drm_bridge_state *(*atomic_duplicate_state)(struct drm_bridge *bridge);
+
+ /**
+ * @atomic_destroy_state:
+ *
+ * Destroy a bridge state object previously allocated by
+ * &drm_bridge_funcs.atomic_duplicate_state().
+ *
+ * The atomic_destroy_state hook is mandatory if the bridge implements
+ * any of the atomic hooks, and should be left unassigned otherwise.
+ * For bridges that don't subclass &drm_bridge_state, the
+ * drm_atomic_helper_bridge_destroy_state() helper function shall be
+ * used to implement this hook.
+ */
+ void (*atomic_destroy_state)(struct drm_bridge *bridge,
+ struct drm_bridge_state *state);
+
+ /**
+ * @atomic_get_output_bus_fmts:
+ *
+ * Return the supported bus formats on the output end of a bridge.
+ * The returned array must be allocated with kmalloc() and will be
+ * freed by the caller. If the allocation fails, NULL should be
+ * returned. num_output_fmts must be set to the returned array size.
+ * Formats listed in the returned array should be listed in decreasing
+ * preference order (the core will try all formats until it finds one
+ * that works).
+ *
+ * This method is only called on the last element of the bridge chain
+ * as part of the bus format negotiation process that happens in
+ * &drm_atomic_bridge_chain_select_bus_fmts().
+ * This method is optional. When not implemented, the core will
+ * fall back to &drm_connector.display_info.bus_formats[0] if
+ * &drm_connector.display_info.num_bus_formats > 0,
+ * or to MEDIA_BUS_FMT_FIXED otherwise.
+ */
+ u32 *(*atomic_get_output_bus_fmts)(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state,
+ unsigned int *num_output_fmts);
+
+ /**
+ * @atomic_get_input_bus_fmts:
+ *
+ * Return the supported bus formats on the input end of a bridge for
+ * a specific output bus format.
+ *
+ * The returned array must be allocated with kmalloc() and will be
+ * freed by the caller. If the allocation fails, NULL should be
+ * returned. num_output_fmts must be set to the returned array size.
+ * Formats listed in the returned array should be listed in decreasing
+ * preference order (the core will try all formats until it finds one
+ * that works). When the format is not supported NULL should be
+ * returned and num_output_fmts should be set to 0.
+ *
+ * This method is called on all elements of the bridge chain as part of
+ * the bus format negotiation process that happens in
+ * drm_atomic_bridge_chain_select_bus_fmts().
+ * This method is optional. When not implemented, the core will bypass
+ * bus format negotiation on this element of the bridge without
+ * failing, and the previous element in the chain will be passed
+ * MEDIA_BUS_FMT_FIXED as its output bus format.
+ *
+ * Bridge drivers that need to support being linked to bridges that are
+ * not supporting bus format negotiation should handle the
+ * output_fmt == MEDIA_BUS_FMT_FIXED case appropriately, by selecting a
+ * sensible default value or extracting this information from somewhere
+ * else (FW property, &drm_display_mode, &drm_display_info, ...)
+ *
+ * Note: Even if input format selection on the first bridge has no
+ * impact on the negotiation process (bus format negotiation stops once
+ * we reach the first element of the chain), drivers are expected to
+ * return accurate input formats as the input format may be used to
+ * configure the CRTC output appropriately.
+ */
+ u32 *(*atomic_get_input_bus_fmts)(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state,
+ u32 output_fmt,
+ unsigned int *num_input_fmts);
+
+ /**
+ * @atomic_check:
+ *
+ * This method is responsible for checking bridge state correctness.
+ * It can also check the state of the surrounding components in chain
+ * to make sure the whole pipeline can work properly.
+ *
+ * &drm_bridge_funcs.atomic_check() hooks are called in reverse
+ * order (from the last to the first bridge).
+ *
+ * This method is optional. &drm_bridge_funcs.mode_fixup() is not
+ * called when &drm_bridge_funcs.atomic_check() is implemented, so only
+ * one of them should be provided.
+ *
+ * If drivers need to tweak &drm_bridge_state.input_bus_cfg.flags or
+ * &drm_bridge_state.output_bus_cfg.flags it should should happen in
+ * this function. By default the &drm_bridge_state.output_bus_cfg.flags
+ * field is set to the next bridge
+ * &drm_bridge_state.input_bus_cfg.flags value or
+ * &drm_connector.display_info.bus_flags if the bridge is the last
+ * element in the chain.
+ *
+ * RETURNS:
+ * zero if the check passed, a negative error code otherwise.
+ */
+ int (*atomic_check)(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state);
+
+ /**
+ * @atomic_reset:
+ *
+ * Reset the bridge to a predefined state (or retrieve its current
+ * state) and return a &drm_bridge_state object matching this state.
+ * This function is called at attach time.
+ *
+ * The atomic_reset hook is mandatory if the bridge implements any of
+ * the atomic hooks, and should be left unassigned otherwise. For
+ * bridges that don't subclass &drm_bridge_state, the
+ * drm_atomic_helper_bridge_reset() helper function shall be used to
+ * implement this hook.
+ *
+ * Note that the atomic_reset() semantics is not exactly matching the
+ * reset() semantics found on other components (connector, plane, ...).
+ *
+ * 1. The reset operation happens when the bridge is attached, not when
+ * drm_mode_config_reset() is called
+ * 2. It's meant to be used exclusively on bridges that have been
+ * converted to the ATOMIC API
+ *
+ * RETURNS:
+ * A valid drm_bridge_state object in case of success, an ERR_PTR()
+ * giving the reason of the failure otherwise.
+ */
+ struct drm_bridge_state *(*atomic_reset)(struct drm_bridge *bridge);
+
+ /**
+ * @detect:
+ *
+ * Check if anything is attached to the bridge output.
+ *
+ * This callback is optional, if not implemented the bridge will be
+ * considered as always having a component attached to its output.
+ * Bridges that implement this callback shall set the
+ * DRM_BRIDGE_OP_DETECT flag in their &drm_bridge->ops.
+ *
+ * RETURNS:
+ *
+ * drm_connector_status indicating the bridge output status.
+ */
+ enum drm_connector_status (*detect)(struct drm_bridge *bridge);
+
+ /**
+ * @get_modes:
+ *
+ * Fill all modes currently valid for the sink into the &drm_connector
+ * with drm_mode_probed_add().
+ *
+ * The @get_modes callback is mostly intended to support non-probeable
+ * displays such as many fixed panels. Bridges that support reading
+ * EDID shall leave @get_modes unimplemented and implement the
+ * &drm_bridge_funcs->get_edid callback instead.
+ *
+ * This callback is optional. Bridges that implement it shall set the
+ * DRM_BRIDGE_OP_MODES flag in their &drm_bridge->ops.
+ *
+ * The connector parameter shall be used for the sole purpose of
+ * filling modes, and shall not be stored internally by bridge drivers
+ * for future usage.
+ *
+ * RETURNS:
+ *
+ * The number of modes added by calling drm_mode_probed_add().
+ */
+ int (*get_modes)(struct drm_bridge *bridge,
+ struct drm_connector *connector);
+
+ /**
+ * @get_edid:
+ *
+ * Read and parse the EDID data of the connected display.
+ *
+ * The @get_edid callback is the preferred way of reporting mode
+ * information for a display connected to the bridge output. Bridges
+ * that support reading EDID shall implement this callback and leave
+ * the @get_modes callback unimplemented.
+ *
+ * The caller of this operation shall first verify the output
+ * connection status and refrain from reading EDID from a disconnected
+ * output.
+ *
+ * This callback is optional. Bridges that implement it shall set the
+ * DRM_BRIDGE_OP_EDID flag in their &drm_bridge->ops.
+ *
+ * The connector parameter shall be used for the sole purpose of EDID
+ * retrieval and parsing, and shall not be stored internally by bridge
+ * drivers for future usage.
+ *
+ * RETURNS:
+ *
+ * An edid structure newly allocated with kmalloc() (or similar) on
+ * success, or NULL otherwise. The caller is responsible for freeing
+ * the returned edid structure with kfree().
+ */
+ struct edid *(*get_edid)(struct drm_bridge *bridge,
+ struct drm_connector *connector);
+
+ /**
+ * @hpd_notify:
+ *
+ * Notify the bridge of hot plug detection.
+ *
+ * This callback is optional, it may be implemented by bridges that
+ * need to be notified of display connection or disconnection for
+ * internal reasons. One use case is to reset the internal state of CEC
+ * controllers for HDMI bridges.
+ */
+ void (*hpd_notify)(struct drm_bridge *bridge,
+ enum drm_connector_status status);
+
+ /**
+ * @hpd_enable:
+ *
+ * Enable hot plug detection. From now on the bridge shall call
+ * drm_bridge_hpd_notify() each time a change is detected in the output
+ * connection status, until hot plug detection gets disabled with
+ * @hpd_disable.
+ *
+ * This callback is optional and shall only be implemented by bridges
+ * that support hot-plug notification without polling. Bridges that
+ * implement it shall also implement the @hpd_disable callback and set
+ * the DRM_BRIDGE_OP_HPD flag in their &drm_bridge->ops.
+ */
+ void (*hpd_enable)(struct drm_bridge *bridge);
+
+ /**
+ * @hpd_disable:
+ *
+ * Disable hot plug detection. Once this function returns the bridge
+ * shall not call drm_bridge_hpd_notify() when a change in the output
+ * connection status occurs.
+ *
+ * This callback is optional and shall only be implemented by bridges
+ * that support hot-plug notification without polling. Bridges that
+ * implement it shall also implement the @hpd_enable callback and set
+ * the DRM_BRIDGE_OP_HPD flag in their &drm_bridge->ops.
+ */
+ void (*hpd_disable)(struct drm_bridge *bridge);
};
/**
@@ -244,14 +634,13 @@ struct drm_bridge_funcs {
*/
struct drm_bridge_timings {
/**
- * @sampling_edge:
+ * @input_bus_flags:
*
- * Tells whether the bridge samples the digital input signal
- * from the display engine on the positive or negative edge of the
- * clock, this should reuse the DRM_BUS_FLAG_PIXDATA_[POS|NEG]EDGE
- * bitwise flags from the DRM connector (bit 2 and 3 valid).
+ * Tells what additional settings for the pixel data on the bus
+ * this bridge requires (like pixel signal polarity). See also
+ * &drm_display_info->bus_flags.
*/
- u32 sampling_edge;
+ u32 input_bus_flags;
/**
* @setup_time_ps:
*
@@ -266,18 +655,61 @@ struct drm_bridge_timings {
* input signal after the clock edge.
*/
u32 hold_time_ps;
+ /**
+ * @dual_link:
+ *
+ * True if the bus operates in dual-link mode. The exact meaning is
+ * dependent on the bus type. For LVDS buses, this indicates that even-
+ * and odd-numbered pixels are received on separate links.
+ */
+ bool dual_link;
+};
+
+/**
+ * enum drm_bridge_ops - Bitmask of operations supported by the bridge
+ */
+enum drm_bridge_ops {
+ /**
+ * @DRM_BRIDGE_OP_DETECT: The bridge can detect displays connected to
+ * its output. Bridges that set this flag shall implement the
+ * &drm_bridge_funcs->detect callback.
+ */
+ DRM_BRIDGE_OP_DETECT = BIT(0),
+ /**
+ * @DRM_BRIDGE_OP_EDID: The bridge can retrieve the EDID of the display
+ * connected to its output. Bridges that set this flag shall implement
+ * the &drm_bridge_funcs->get_edid callback.
+ */
+ DRM_BRIDGE_OP_EDID = BIT(1),
+ /**
+ * @DRM_BRIDGE_OP_HPD: The bridge can detect hot-plug and hot-unplug
+ * without requiring polling. Bridges that set this flag shall
+ * implement the &drm_bridge_funcs->hpd_enable and
+ * &drm_bridge_funcs->hpd_disable callbacks if they support enabling
+ * and disabling hot-plug detection dynamically.
+ */
+ DRM_BRIDGE_OP_HPD = BIT(2),
+ /**
+ * @DRM_BRIDGE_OP_MODES: The bridge can retrieve the modes supported
+ * by the display at its output. This does not include reading EDID
+ * which is separately covered by @DRM_BRIDGE_OP_EDID. Bridges that set
+ * this flag shall implement the &drm_bridge_funcs->get_modes callback.
+ */
+ DRM_BRIDGE_OP_MODES = BIT(3),
};
/**
* struct drm_bridge - central DRM bridge control structure
*/
struct drm_bridge {
+ /** @base: inherit from &drm_private_object */
+ struct drm_private_obj base;
/** @dev: DRM device this bridge belongs to */
struct drm_device *dev;
/** @encoder: encoder to which this bridge is connected */
struct drm_encoder *encoder;
- /** @next: the next bridge in the encoder chain */
- struct drm_bridge *next;
+ /** @chain_node: used to form a bridge chain */
+ struct list_head chain_node;
#ifdef CONFIG_OF
/** @of_node: device node pointer to the bridge */
struct device_node *of_node;
@@ -294,34 +726,169 @@ struct drm_bridge {
const struct drm_bridge_funcs *funcs;
/** @driver_private: pointer to the bridge driver's internal context */
void *driver_private;
+ /** @ops: bitmask of operations supported by the bridge */
+ enum drm_bridge_ops ops;
+ /**
+ * @type: Type of the connection at the bridge output
+ * (DRM_MODE_CONNECTOR_*). For bridges at the end of this chain this
+ * identifies the type of connected display.
+ */
+ int type;
+ /**
+ * @interlace_allowed: Indicate that the bridge can handle interlaced
+ * modes.
+ */
+ bool interlace_allowed;
+ /**
+ * @ddc: Associated I2C adapter for DDC access, if any.
+ */
+ struct i2c_adapter *ddc;
+ /** private: */
+ /**
+ * @hpd_mutex: Protects the @hpd_cb and @hpd_data fields.
+ */
+ struct rwlock hpd_mutex;
+ /**
+ * @hpd_cb: Hot plug detection callback, registered with
+ * drm_bridge_hpd_enable().
+ */
+ void (*hpd_cb)(void *data, enum drm_connector_status status);
+ /**
+ * @hpd_data: Private data passed to the Hot plug detection callback
+ * @hpd_cb.
+ */
+ void *hpd_data;
};
+static inline struct drm_bridge *
+drm_priv_to_bridge(struct drm_private_obj *priv)
+{
+ return container_of(priv, struct drm_bridge, base);
+}
+
void drm_bridge_add(struct drm_bridge *bridge);
void drm_bridge_remove(struct drm_bridge *bridge);
struct drm_bridge *of_drm_find_bridge(struct device_node *np);
int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
- struct drm_bridge *previous);
+ struct drm_bridge *previous,
+ enum drm_bridge_attach_flags flags);
-bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode);
-enum drm_mode_status drm_bridge_mode_valid(struct drm_bridge *bridge,
- const struct drm_display_mode *mode);
-void drm_bridge_disable(struct drm_bridge *bridge);
-void drm_bridge_post_disable(struct drm_bridge *bridge);
-void drm_bridge_mode_set(struct drm_bridge *bridge,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode);
-void drm_bridge_pre_enable(struct drm_bridge *bridge);
-void drm_bridge_enable(struct drm_bridge *bridge);
+/**
+ * drm_bridge_get_next_bridge() - Get the next bridge in the chain
+ * @bridge: bridge object
+ *
+ * RETURNS:
+ * the next bridge in the chain after @bridge, or NULL if @bridge is the last.
+ */
+static inline struct drm_bridge *
+drm_bridge_get_next_bridge(struct drm_bridge *bridge)
+{
+ if (list_is_last(&bridge->chain_node, &bridge->encoder->bridge_chain))
+ return NULL;
+
+ return list_next_entry(bridge, chain_node);
+}
+
+/**
+ * drm_bridge_get_prev_bridge() - Get the previous bridge in the chain
+ * @bridge: bridge object
+ *
+ * RETURNS:
+ * the previous bridge in the chain, or NULL if @bridge is the first.
+ */
+static inline struct drm_bridge *
+drm_bridge_get_prev_bridge(struct drm_bridge *bridge)
+{
+ if (list_is_first(&bridge->chain_node, &bridge->encoder->bridge_chain))
+ return NULL;
+
+ return list_prev_entry(bridge, chain_node);
+}
+
+/**
+ * drm_bridge_chain_get_first_bridge() - Get the first bridge in the chain
+ * @encoder: encoder object
+ *
+ * RETURNS:
+ * the first bridge in the chain, or NULL if @encoder has no bridge attached
+ * to it.
+ */
+static inline struct drm_bridge *
+drm_bridge_chain_get_first_bridge(struct drm_encoder *encoder)
+{
+ return list_first_entry_or_null(&encoder->bridge_chain,
+ struct drm_bridge, chain_node);
+}
+
+/**
+ * drm_for_each_bridge_in_chain() - Iterate over all bridges present in a chain
+ * @encoder: the encoder to iterate bridges on
+ * @bridge: a bridge pointer updated to point to the current bridge at each
+ * iteration
+ *
+ * Iterate over all bridges present in the bridge chain attached to @encoder.
+ */
+#define drm_for_each_bridge_in_chain(encoder, bridge) \
+ list_for_each_entry(bridge, &(encoder)->bridge_chain, chain_node)
+
+bool drm_bridge_chain_mode_fixup(struct drm_bridge *bridge,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
+enum drm_mode_status
+drm_bridge_chain_mode_valid(struct drm_bridge *bridge,
+ const struct drm_display_mode *mode);
+void drm_bridge_chain_disable(struct drm_bridge *bridge);
+void drm_bridge_chain_post_disable(struct drm_bridge *bridge);
+void drm_bridge_chain_mode_set(struct drm_bridge *bridge,
+ const struct drm_display_mode *mode,
+ const struct drm_display_mode *adjusted_mode);
+void drm_bridge_chain_pre_enable(struct drm_bridge *bridge);
+void drm_bridge_chain_enable(struct drm_bridge *bridge);
+
+int drm_atomic_bridge_chain_check(struct drm_bridge *bridge,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state);
+void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge,
+ struct drm_atomic_state *state);
+void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge,
+ struct drm_atomic_state *state);
+void drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge,
+ struct drm_atomic_state *state);
+void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge,
+ struct drm_atomic_state *state);
+
+u32 *
+drm_atomic_helper_bridge_propagate_bus_fmt(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state,
+ u32 output_fmt,
+ unsigned int *num_input_fmts);
+
+enum drm_connector_status drm_bridge_detect(struct drm_bridge *bridge);
+int drm_bridge_get_modes(struct drm_bridge *bridge,
+ struct drm_connector *connector);
+struct edid *drm_bridge_get_edid(struct drm_bridge *bridge,
+ struct drm_connector *connector);
+void drm_bridge_hpd_enable(struct drm_bridge *bridge,
+ void (*cb)(void *data,
+ enum drm_connector_status status),
+ void *data);
+void drm_bridge_hpd_disable(struct drm_bridge *bridge);
+void drm_bridge_hpd_notify(struct drm_bridge *bridge,
+ enum drm_connector_status status);
#ifdef CONFIG_DRM_PANEL_BRIDGE
-struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel,
- u32 connector_type);
+struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel);
+struct drm_bridge *drm_panel_bridge_add_typed(struct drm_panel *panel,
+ u32 connector_type);
void drm_panel_bridge_remove(struct drm_bridge *bridge);
struct drm_bridge *devm_drm_panel_bridge_add(struct device *dev,
- struct drm_panel *panel,
- u32 connector_type);
+ struct drm_panel *panel);
+struct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev,
+ struct drm_panel *panel,
+ u32 connector_type);
+struct drm_connector *drm_panel_bridge_connector(struct drm_bridge *bridge);
#endif
#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_cache.h b/sys/dev/pci/drm/include/drm/drm_cache.h
index 820ebb32bad..3b4081572ba 100644
--- a/sys/dev/pci/drm/include/drm/drm_cache.h
+++ b/sys/dev/pci/drm/include/drm/drm_cache.h
@@ -1,4 +1,3 @@
-/* $OpenBSD: drm_cache.h,v 1.1 2019/04/14 10:14:52 jsg Exp $ */
/**************************************************************************
*
* Copyright 2009 Red Hat Inc.
@@ -35,17 +34,20 @@
#define _DRM_CACHE_H_
#include <linux/scatterlist.h>
-#include <uvm/uvm_extern.h>
void drm_clflush_pages(struct vm_page *pages[], unsigned long num_pages);
+void drm_clflush_sg(struct sg_table *st);
+void drm_clflush_virt_range(void *addr, unsigned long length);
+bool drm_need_swiotlb(int dma_bits);
+
static inline bool drm_arch_can_wc_memory(void)
{
-#if defined(__powerpc__)
+#if defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE)
return false;
-#elif defined(__mips__)
+#elif defined(CONFIG_MIPS) && defined(CONFIG_CPU_LOONGSON64)
return false;
-#elif defined(__arm__) || defined(__arm64__)
+#elif defined(CONFIG_ARM) || defined(CONFIG_ARM64)
/*
* The DRM driver stack is designed to work with cache coherent devices
* only, but permits an optimization to be enabled in some cases, where
diff --git a/sys/dev/pci/drm/include/drm/drm_client.h b/sys/dev/pci/drm/include/drm/drm_client.h
new file mode 100644
index 00000000000..19375f8cd15
--- /dev/null
+++ b/sys/dev/pci/drm/include/drm/drm_client.h
@@ -0,0 +1,193 @@
+/* SPDX-License-Identifier: GPL-2.0 or MIT */
+
+#ifndef _DRM_CLIENT_H_
+#define _DRM_CLIENT_H_
+
+#include <linux/lockdep.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+
+#include <drm/drm_connector.h>
+#include <drm/drm_crtc.h>
+
+struct drm_client_dev;
+struct drm_device;
+struct drm_file;
+struct drm_framebuffer;
+struct drm_gem_object;
+struct drm_minor;
+struct module;
+
+/**
+ * struct drm_client_funcs - DRM client callbacks
+ */
+struct drm_client_funcs {
+ /**
+ * @owner: The module owner
+ */
+ struct module *owner;
+
+ /**
+ * @unregister:
+ *
+ * Called when &drm_device is unregistered. The client should respond by
+ * releasing its resources using drm_client_release().
+ *
+ * This callback is optional.
+ */
+ void (*unregister)(struct drm_client_dev *client);
+
+ /**
+ * @restore:
+ *
+ * Called on drm_lastclose(). The first client instance in the list that
+ * returns zero gets the privilege to restore and no more clients are
+ * called. This callback is not called after @unregister has been called.
+ *
+ * Note that the core does not guarantee exclusion against concurrent
+ * drm_open(). Clients need to ensure this themselves, for example by
+ * using drm_master_internal_acquire() and
+ * drm_master_internal_release().
+ *
+ * This callback is optional.
+ */
+ int (*restore)(struct drm_client_dev *client);
+
+ /**
+ * @hotplug:
+ *
+ * Called on drm_kms_helper_hotplug_event().
+ * This callback is not called after @unregister has been called.
+ *
+ * This callback is optional.
+ */
+ int (*hotplug)(struct drm_client_dev *client);
+};
+
+/**
+ * struct drm_client_dev - DRM client instance
+ */
+struct drm_client_dev {
+ /**
+ * @dev: DRM device
+ */
+ struct drm_device *dev;
+
+ /**
+ * @name: Name of the client.
+ */
+ const char *name;
+
+ /**
+ * @list:
+ *
+ * List of all clients of a DRM device, linked into
+ * &drm_device.clientlist. Protected by &drm_device.clientlist_mutex.
+ */
+ struct list_head list;
+
+ /**
+ * @funcs: DRM client functions (optional)
+ */
+ const struct drm_client_funcs *funcs;
+
+ /**
+ * @file: DRM file
+ */
+ struct drm_file *file;
+
+ /**
+ * @modeset_mutex: Protects @modesets.
+ */
+ struct rwlock modeset_mutex;
+
+ /**
+ * @modesets: CRTC configurations
+ */
+ struct drm_mode_set *modesets;
+};
+
+int drm_client_init(struct drm_device *dev, struct drm_client_dev *client,
+ const char *name, const struct drm_client_funcs *funcs);
+void drm_client_release(struct drm_client_dev *client);
+void drm_client_register(struct drm_client_dev *client);
+
+void drm_client_dev_unregister(struct drm_device *dev);
+void drm_client_dev_hotplug(struct drm_device *dev);
+void drm_client_dev_restore(struct drm_device *dev);
+
+/**
+ * struct drm_client_buffer - DRM client buffer
+ */
+struct drm_client_buffer {
+ /**
+ * @client: DRM client
+ */
+ struct drm_client_dev *client;
+
+ /**
+ * @handle: Buffer handle
+ */
+ u32 handle;
+
+ /**
+ * @pitch: Buffer pitch
+ */
+ u32 pitch;
+
+ /**
+ * @gem: GEM object backing this buffer
+ */
+ struct drm_gem_object *gem;
+
+ /**
+ * @vaddr: Virtual address for the buffer
+ */
+ void *vaddr;
+
+ /**
+ * @fb: DRM framebuffer
+ */
+ struct drm_framebuffer *fb;
+};
+
+struct drm_client_buffer *
+drm_client_framebuffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format);
+void drm_client_framebuffer_delete(struct drm_client_buffer *buffer);
+void *drm_client_buffer_vmap(struct drm_client_buffer *buffer);
+void drm_client_buffer_vunmap(struct drm_client_buffer *buffer);
+
+int drm_client_modeset_create(struct drm_client_dev *client);
+void drm_client_modeset_free(struct drm_client_dev *client);
+int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width, unsigned int height);
+bool drm_client_rotation(struct drm_mode_set *modeset, unsigned int *rotation);
+int drm_client_modeset_commit_locked(struct drm_client_dev *client);
+int drm_client_modeset_commit(struct drm_client_dev *client);
+int drm_client_modeset_dpms(struct drm_client_dev *client, int mode);
+
+/**
+ * drm_client_for_each_modeset() - Iterate over client modesets
+ * @modeset: &drm_mode_set loop cursor
+ * @client: DRM client
+ */
+#define drm_client_for_each_modeset(modeset, client) \
+ for (({ lockdep_assert_held(&(client)->modeset_mutex); }), \
+ modeset = (client)->modesets; modeset->crtc; modeset++)
+
+/**
+ * drm_client_for_each_connector_iter - connector_list iterator macro
+ * @connector: &struct drm_connector pointer used as cursor
+ * @iter: &struct drm_connector_list_iter
+ *
+ * This iterates the connectors that are useable for internal clients (excludes
+ * writeback connectors).
+ *
+ * For more info see drm_for_each_connector_iter().
+ */
+#define drm_client_for_each_connector_iter(connector, iter) \
+ drm_for_each_connector_iter(connector, iter) \
+ if (connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK)
+
+int drm_client_debugfs_init(struct drm_minor *minor);
+
+#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_color_mgmt.h b/sys/dev/pci/drm/include/drm/drm_color_mgmt.h
index 44f04233e3d..81c298488b0 100644
--- a/sys/dev/pci/drm/include/drm/drm_color_mgmt.h
+++ b/sys/dev/pci/drm/include/drm/drm_color_mgmt.h
@@ -24,11 +24,35 @@
#define __DRM_COLOR_MGMT_H__
#include <linux/ctype.h>
+#include <drm/drm_property.h>
struct drm_crtc;
struct drm_plane;
-uint32_t drm_color_lut_extract(uint32_t user_input, uint32_t bit_precision);
+/**
+ * drm_color_lut_extract - clamp and round LUT entries
+ * @user_input: input value
+ * @bit_precision: number of bits the hw LUT supports
+ *
+ * Extract a degamma/gamma LUT value provided by user (in the form of
+ * &drm_color_lut entries) and round it to the precision supported by the
+ * hardware.
+ */
+static inline u32 drm_color_lut_extract(u32 user_input, int bit_precision)
+{
+ u32 val = user_input;
+ u32 max = 0xffff >> (16 - bit_precision);
+
+ /* Round only if we're not using full precision. */
+ if (bit_precision < 16) {
+ val += 1UL << (16 - bit_precision - 1);
+ val >>= 16 - bit_precision;
+ }
+
+ return clamp_val(val, 0, max);
+}
+
+u64 drm_color_ctm_s31_32_to_qm_n(u64 user_input, u32 m, u32 n);
void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
uint degamma_lut_size,
@@ -68,4 +92,32 @@ int drm_plane_create_color_properties(struct drm_plane *plane,
u32 supported_ranges,
enum drm_color_encoding default_encoding,
enum drm_color_range default_range);
+
+/**
+ * enum drm_color_lut_tests - hw-specific LUT tests to perform
+ *
+ * The drm_color_lut_check() function takes a bitmask of the values here to
+ * determine which tests to apply to a userspace-provided LUT.
+ */
+enum drm_color_lut_tests {
+ /**
+ * @DRM_COLOR_LUT_EQUAL_CHANNELS:
+ *
+ * Checks whether the entries of a LUT all have equal values for the
+ * red, green, and blue channels. Intended for hardware that only
+ * accepts a single value per LUT entry and assumes that value applies
+ * to all three color components.
+ */
+ DRM_COLOR_LUT_EQUAL_CHANNELS = BIT(0),
+
+ /**
+ * @DRM_COLOR_LUT_NON_DECREASING:
+ *
+ * Checks whether the entries of a LUT are always flat or increasing
+ * (never decreasing).
+ */
+ DRM_COLOR_LUT_NON_DECREASING = BIT(1),
+};
+
+int drm_color_lut_check(const struct drm_property_blob *lut, u32 tests);
#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_connector.h b/sys/dev/pci/drm/include/drm/drm_connector.h
index 8b7da93d13e..f5d6c6b72f3 100644
--- a/sys/dev/pci/drm/include/drm/drm_connector.h
+++ b/sys/dev/pci/drm/include/drm/drm_connector.h
@@ -28,6 +28,7 @@
#include <linux/ctype.h>
#include <linux/hdmi.h>
#include <drm/drm_mode_object.h>
+#include <drm/drm_util.h>
#include <uapi/drm/drm_mode.h>
@@ -40,6 +41,7 @@ struct drm_property;
struct drm_property_blob;
struct drm_printer;
struct edid;
+struct i2c_adapter;
enum drm_connector_force {
DRM_FORCE_UNSPECIFIED,
@@ -81,6 +83,53 @@ enum drm_connector_status {
connector_status_unknown = 3,
};
+/**
+ * enum drm_connector_registration_status - userspace registration status for
+ * a &drm_connector
+ *
+ * This enum is used to track the status of initializing a connector and
+ * registering it with userspace, so that DRM can prevent bogus modesets on
+ * connectors that no longer exist.
+ */
+enum drm_connector_registration_state {
+ /**
+ * @DRM_CONNECTOR_INITIALIZING: The connector has just been created,
+ * but has yet to be exposed to userspace. There should be no
+ * additional restrictions to how the state of this connector may be
+ * modified.
+ */
+ DRM_CONNECTOR_INITIALIZING = 0,
+
+ /**
+ * @DRM_CONNECTOR_REGISTERED: The connector has been fully initialized
+ * and registered with sysfs, as such it has been exposed to
+ * userspace. There should be no additional restrictions to how the
+ * state of this connector may be modified.
+ */
+ DRM_CONNECTOR_REGISTERED = 1,
+
+ /**
+ * @DRM_CONNECTOR_UNREGISTERED: The connector has either been exposed
+ * to userspace and has since been unregistered and removed from
+ * userspace, or the connector was unregistered before it had a chance
+ * to be exposed to userspace (e.g. still in the
+ * @DRM_CONNECTOR_INITIALIZING state). When a connector is
+ * unregistered, there are additional restrictions to how its state
+ * may be modified:
+ *
+ * - An unregistered connector may only have its DPMS changed from
+ * On->Off. Once DPMS is changed to Off, it may not be switched back
+ * to On.
+ * - Modesets are not allowed on unregistered connectors, unless they
+ * would result in disabling its assigned CRTCs. This means
+ * disabling a CRTC on an unregistered connector is OK, but enabling
+ * one is not.
+ * - Removing a CRTC from an unregistered connector is OK, but new
+ * CRTCs may never be assigned to an unregistered connector.
+ */
+ DRM_CONNECTOR_UNREGISTERED = 2,
+};
+
enum subpixel_order {
SubPixelUnknown = 0,
SubPixelHorizontalRGB,
@@ -139,19 +188,19 @@ struct drm_hdmi_info {
/**
* @y420_vdb_modes: bitmap of modes which can support ycbcr420
- * output only (not normal RGB/YCBCR444/422 outputs). There are total
- * 107 VICs defined by CEA-861-F spec, so the size is 128 bits to map
- * upto 128 VICs;
+ * output only (not normal RGB/YCBCR444/422 outputs). The max VIC
+ * defined by the CEA-861-G spec is 219, so the size is 256 bits to map
+ * up to 256 VICs.
*/
- unsigned long y420_vdb_modes[BITS_TO_LONGS(128)];
+ unsigned long y420_vdb_modes[BITS_TO_LONGS(256)];
/**
* @y420_cmdb_modes: bitmap of modes which can support ycbcr420
- * output also, along with normal HDMI outputs. There are total 107
- * VICs defined by CEA-861-F spec, so the size is 128 bits to map upto
- * 128 VICs;
+ * output also, along with normal HDMI outputs. The max VIC defined by
+ * the CEA-861-G spec is 219, so the size is 256 bits to map up to 256
+ * VICs.
*/
- unsigned long y420_cmdb_modes[BITS_TO_LONGS(128)];
+ unsigned long y420_cmdb_modes[BITS_TO_LONGS(256)];
/** @y420_cmdb_map: bitmap of SVD index, to extraxt vcb modes */
u64 y420_cmdb_map;
@@ -206,6 +255,120 @@ enum drm_panel_orientation {
};
/**
+ * struct drm_monitor_range_info - Panel's Monitor range in EDID for
+ * &drm_display_info
+ *
+ * This struct is used to store a frequency range supported by panel
+ * as parsed from EDID's detailed monitor range descriptor block.
+ *
+ * @min_vfreq: This is the min supported refresh rate in Hz from
+ * EDID's detailed monitor range.
+ * @max_vfreq: This is the max supported refresh rate in Hz from
+ * EDID's detailed monitor range
+ */
+struct drm_monitor_range_info {
+ u8 min_vfreq;
+ u8 max_vfreq;
+};
+
+/*
+ * This is a consolidated colorimetry list supported by HDMI and
+ * DP protocol standard. The respective connectors will register
+ * a property with the subset of this list (supported by that
+ * respective protocol). Userspace will set the colorspace through
+ * a colorspace property which will be created and exposed to
+ * userspace.
+ */
+
+/* For Default case, driver will set the colorspace */
+#define DRM_MODE_COLORIMETRY_DEFAULT 0
+/* CEA 861 Normal Colorimetry options */
+#define DRM_MODE_COLORIMETRY_NO_DATA 0
+#define DRM_MODE_COLORIMETRY_SMPTE_170M_YCC 1
+#define DRM_MODE_COLORIMETRY_BT709_YCC 2
+/* CEA 861 Extended Colorimetry Options */
+#define DRM_MODE_COLORIMETRY_XVYCC_601 3
+#define DRM_MODE_COLORIMETRY_XVYCC_709 4
+#define DRM_MODE_COLORIMETRY_SYCC_601 5
+#define DRM_MODE_COLORIMETRY_OPYCC_601 6
+#define DRM_MODE_COLORIMETRY_OPRGB 7
+#define DRM_MODE_COLORIMETRY_BT2020_CYCC 8
+#define DRM_MODE_COLORIMETRY_BT2020_RGB 9
+#define DRM_MODE_COLORIMETRY_BT2020_YCC 10
+/* Additional Colorimetry extension added as part of CTA 861.G */
+#define DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65 11
+#define DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER 12
+/* Additional Colorimetry Options added for DP 1.4a VSC Colorimetry Format */
+#define DRM_MODE_COLORIMETRY_RGB_WIDE_FIXED 13
+#define DRM_MODE_COLORIMETRY_RGB_WIDE_FLOAT 14
+#define DRM_MODE_COLORIMETRY_BT601_YCC 15
+
+/**
+ * enum drm_bus_flags - bus_flags info for &drm_display_info
+ *
+ * This enum defines signal polarities and clock edge information for signals on
+ * a bus as bitmask flags.
+ *
+ * The clock edge information is conveyed by two sets of symbols,
+ * DRM_BUS_FLAGS_*_DRIVE_\* and DRM_BUS_FLAGS_*_SAMPLE_\*. When this enum is
+ * used to describe a bus from the point of view of the transmitter, the
+ * \*_DRIVE_\* flags should be used. When used from the point of view of the
+ * receiver, the \*_SAMPLE_\* flags should be used. The \*_DRIVE_\* and
+ * \*_SAMPLE_\* flags alias each other, with the \*_SAMPLE_POSEDGE and
+ * \*_SAMPLE_NEGEDGE flags being equal to \*_DRIVE_NEGEDGE and \*_DRIVE_POSEDGE
+ * respectively. This simplifies code as signals are usually sampled on the
+ * opposite edge of the driving edge. Transmitters and receivers may however
+ * need to take other signal timings into account to convert between driving
+ * and sample edges.
+ *
+ * @DRM_BUS_FLAG_DE_LOW: The Data Enable signal is active low
+ * @DRM_BUS_FLAG_DE_HIGH: The Data Enable signal is active high
+ * @DRM_BUS_FLAG_PIXDATA_POSEDGE: Legacy value, do not use
+ * @DRM_BUS_FLAG_PIXDATA_NEGEDGE: Legacy value, do not use
+ * @DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE: Data is driven on the rising edge of
+ * the pixel clock
+ * @DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE: Data is driven on the falling edge of
+ * the pixel clock
+ * @DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE: Data is sampled on the rising edge of
+ * the pixel clock
+ * @DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE: Data is sampled on the falling edge of
+ * the pixel clock
+ * @DRM_BUS_FLAG_DATA_MSB_TO_LSB: Data is transmitted MSB to LSB on the bus
+ * @DRM_BUS_FLAG_DATA_LSB_TO_MSB: Data is transmitted LSB to MSB on the bus
+ * @DRM_BUS_FLAG_SYNC_POSEDGE: Legacy value, do not use
+ * @DRM_BUS_FLAG_SYNC_NEGEDGE: Legacy value, do not use
+ * @DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE: Sync signals are driven on the rising
+ * edge of the pixel clock
+ * @DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE: Sync signals are driven on the falling
+ * edge of the pixel clock
+ * @DRM_BUS_FLAG_SYNC_SAMPLE_POSEDGE: Sync signals are sampled on the rising
+ * edge of the pixel clock
+ * @DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE: Sync signals are sampled on the falling
+ * edge of the pixel clock
+ * @DRM_BUS_FLAG_SHARP_SIGNALS: Set if the Sharp-specific signals
+ * (SPL, CLS, PS, REV) must be used
+ */
+enum drm_bus_flags {
+ DRM_BUS_FLAG_DE_LOW = BIT(0),
+ DRM_BUS_FLAG_DE_HIGH = BIT(1),
+ DRM_BUS_FLAG_PIXDATA_POSEDGE = BIT(2),
+ DRM_BUS_FLAG_PIXDATA_NEGEDGE = BIT(3),
+ DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE = DRM_BUS_FLAG_PIXDATA_POSEDGE,
+ DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE = DRM_BUS_FLAG_PIXDATA_NEGEDGE,
+ DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE = DRM_BUS_FLAG_PIXDATA_NEGEDGE,
+ DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE = DRM_BUS_FLAG_PIXDATA_POSEDGE,
+ DRM_BUS_FLAG_DATA_MSB_TO_LSB = BIT(4),
+ DRM_BUS_FLAG_DATA_LSB_TO_MSB = BIT(5),
+ DRM_BUS_FLAG_SYNC_POSEDGE = BIT(6),
+ DRM_BUS_FLAG_SYNC_NEGEDGE = BIT(7),
+ DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE = DRM_BUS_FLAG_SYNC_POSEDGE,
+ DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE = DRM_BUS_FLAG_SYNC_NEGEDGE,
+ DRM_BUS_FLAG_SYNC_SAMPLE_POSEDGE = DRM_BUS_FLAG_SYNC_NEGEDGE,
+ DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE = DRM_BUS_FLAG_SYNC_POSEDGE,
+ DRM_BUS_FLAG_SHARP_SIGNALS = BIT(8),
+};
+
+/**
* struct drm_display_info - runtime data about the connected sink
*
* Describes a given display (e.g. CRT or flat panel) and its limitations. For
@@ -218,26 +381,16 @@ enum drm_panel_orientation {
*/
struct drm_display_info {
/**
- * @name: Name of the display.
- */
- char name[DRM_DISPLAY_INFO_LEN];
-
- /**
* @width_mm: Physical width in mm.
*/
- unsigned int width_mm;
+ unsigned int width_mm;
+
/**
* @height_mm: Physical height in mm.
*/
unsigned int height_mm;
/**
- * @pixel_clock: Maximum pixel clock supported by the sink, in units of
- * 100Hz. This mismatches the clock in &drm_display_mode (which is in
- * kHZ), because that's what the EDID uses as base unit.
- */
- unsigned int pixel_clock;
- /**
* @bpc: Maximum bits per color channel. Used by HDMI and DP outputs.
*/
unsigned int bpc;
@@ -280,24 +433,10 @@ struct drm_display_info {
*/
unsigned int num_bus_formats;
-#define DRM_BUS_FLAG_DE_LOW (1<<0)
-#define DRM_BUS_FLAG_DE_HIGH (1<<1)
-/* drive data on pos. edge */
-#define DRM_BUS_FLAG_PIXDATA_POSEDGE (1<<2)
-/* drive data on neg. edge */
-#define DRM_BUS_FLAG_PIXDATA_NEGEDGE (1<<3)
-/* data is transmitted MSB to LSB on the bus */
-#define DRM_BUS_FLAG_DATA_MSB_TO_LSB (1<<4)
-/* data is transmitted LSB to MSB on the bus */
-#define DRM_BUS_FLAG_DATA_LSB_TO_MSB (1<<5)
-/* drive sync on pos. edge */
-#define DRM_BUS_FLAG_SYNC_POSEDGE (1<<6)
-/* drive sync on neg. edge */
-#define DRM_BUS_FLAG_SYNC_NEGEDGE (1<<7)
-
/**
* @bus_flags: Additional information (like pixel signal polarity) for
- * the pixel data on the bus, using DRM_BUS_FLAGS\_ defines.
+ * the pixel data on the bus, using &enum drm_bus_flags values
+ * DRM_BUS_FLAGS\_.
*/
u32 bus_flags;
@@ -313,11 +452,25 @@ struct drm_display_info {
bool dvi_dual;
/**
+ * @is_hdmi: True if the sink is an HDMI device.
+ *
+ * This field shall be used instead of calling
+ * drm_detect_hdmi_monitor() when possible.
+ */
+ bool is_hdmi;
+
+ /**
* @has_hdmi_infoframe: Does the sink support the HDMI infoframe?
*/
bool has_hdmi_infoframe;
/**
+ * @rgb_quant_range_selectable: Does the sink support selecting
+ * the RGB quantization range?
+ */
+ bool rgb_quant_range_selectable;
+
+ /**
* @edid_hdmi_dc_modes: Mask of supported hdmi deep color modes. Even
* more stuff redundant with @bus_formats.
*/
@@ -337,6 +490,11 @@ struct drm_display_info {
* @non_desktop: Non desktop display (HMD).
*/
bool non_desktop;
+
+ /**
+ * @monitor_range: Frequency range supported by monitor range descriptor
+ */
+ struct drm_monitor_range_info monitor_range;
};
int drm_display_info_set_bus_formats(struct drm_display_info *info,
@@ -344,13 +502,37 @@ int drm_display_info_set_bus_formats(struct drm_display_info *info,
unsigned int num_formats);
/**
+ * struct drm_connector_tv_margins - TV connector related margins
+ *
+ * Describes the margins in pixels to put around the image on TV
+ * connectors to deal with overscan.
+ */
+struct drm_connector_tv_margins {
+ /**
+ * @bottom: Bottom margin in pixels.
+ */
+ unsigned int bottom;
+
+ /**
+ * @left: Left margin in pixels.
+ */
+ unsigned int left;
+
+ /**
+ * @right: Right margin in pixels.
+ */
+ unsigned int right;
+
+ /**
+ * @top: Top margin in pixels.
+ */
+ unsigned int top;
+};
+
+/**
* struct drm_tv_connector_state - TV connector related states
* @subconnector: selected subconnector
- * @margins: margins
- * @margins.left: left margin
- * @margins.right: right margin
- * @margins.top: top margin
- * @margins.bottom: bottom margin
+ * @margins: TV margins
* @mode: TV mode
* @brightness: brightness in percent
* @contrast: contrast in percent
@@ -361,12 +543,7 @@ int drm_display_info_set_bus_formats(struct drm_display_info *info,
*/
struct drm_tv_connector_state {
enum drm_mode_subconnector subconnector;
- struct {
- unsigned int left;
- unsigned int right;
- unsigned int top;
- unsigned int bottom;
- } margins;
+ struct drm_connector_tv_margins margins;
unsigned int mode;
unsigned int brightness;
unsigned int contrast;
@@ -397,6 +574,15 @@ struct drm_connector_state {
* Used by the atomic helpers to select the encoder, through the
* &drm_connector_helper_funcs.atomic_best_encoder or
* &drm_connector_helper_funcs.best_encoder callbacks.
+ *
+ * This is also used in the atomic helpers to map encoders to their
+ * current and previous connectors, see
+ * drm_atomic_get_old_connector_for_encoder() and
+ * drm_atomic_get_new_connector_for_encoder().
+ *
+ * NOTE: Atomic drivers must fill this out (either themselves or through
+ * helpers), for otherwise the GETCONNECTOR and GETENCODER IOCTLs will
+ * not return correct data to userspace.
*/
struct drm_encoder *best_encoder;
@@ -420,6 +606,20 @@ struct drm_connector_state {
struct drm_tv_connector_state tv;
/**
+ * @self_refresh_aware:
+ *
+ * This tracks whether a connector is aware of the self refresh state.
+ * It should be set to true for those connector implementations which
+ * understand the self refresh state. This is needed since the crtc
+ * registers the self refresh helpers and it doesn't know if the
+ * connectors downstream have implemented self refresh entry/exit.
+ *
+ * Drivers should set this to true in atomic_check if they know how to
+ * handle self_refresh requests.
+ */
+ bool self_refresh_aware;
+
+ /**
* @picture_aspect_ratio: Connector property to control the
* HDMI infoframe aspect ratio setting.
*
@@ -437,6 +637,12 @@ struct drm_connector_state {
unsigned int content_type;
/**
+ * @hdcp_content_type: Connector property to pass the type of
+ * protected content. This is most commonly used for HDCP.
+ */
+ unsigned int hdcp_content_type;
+
+ /**
* @scaling_mode: Connector property to control the
* upscaling, mostly used for built-in panels.
*/
@@ -449,6 +655,13 @@ struct drm_connector_state {
unsigned int content_protection;
/**
+ * @colorspace: State variable for Connector property to request
+ * colorspace change on Sink. This is most commonly used to switch
+ * to wider color gamuts like BT2020.
+ */
+ u32 colorspace;
+
+ /**
* @writeback_job: Writeback job for writeback connectors
*
* Holds the framebuffer and out-fence for a writeback connector. As
@@ -460,6 +673,24 @@ struct drm_connector_state {
* drm_writeback_signal_completion()
*/
struct drm_writeback_job *writeback_job;
+
+ /**
+ * @max_requested_bpc: Connector property to limit the maximum bit
+ * depth of the pixels.
+ */
+ u8 max_requested_bpc;
+
+ /**
+ * @max_bpc: Connector max_bpc based on the requested max_bpc property
+ * and the connector bpc limitations obtained from edid.
+ */
+ u8 max_bpc;
+
+ /**
+ * @hdr_output_metadata:
+ * DRM blob property for HDR output metadata
+ */
+ struct drm_property_blob *hdr_output_metadata;
};
/**
@@ -755,19 +986,131 @@ struct drm_connector_funcs {
const struct drm_connector_state *state);
};
-/* mode specified on the command line */
+/**
+ * struct drm_cmdline_mode - DRM Mode passed through the kernel command-line
+ *
+ * Each connector can have an initial mode with additional options
+ * passed through the kernel command line. This structure allows to
+ * express those parameters and will be filled by the command-line
+ * parser.
+ */
struct drm_cmdline_mode {
+ /**
+ * @name:
+ *
+ * Name of the mode.
+ */
+ char name[DRM_DISPLAY_MODE_LEN];
+
+ /**
+ * @specified:
+ *
+ * Has a mode been read from the command-line?
+ */
bool specified;
+
+ /**
+ * @refresh_specified:
+ *
+ * Did the mode have a preferred refresh rate?
+ */
bool refresh_specified;
+
+ /**
+ * @bpp_specified:
+ *
+ * Did the mode have a preferred BPP?
+ */
bool bpp_specified;
- int xres, yres;
+
+ /**
+ * @xres:
+ *
+ * Active resolution on the X axis, in pixels.
+ */
+ int xres;
+
+ /**
+ * @yres:
+ *
+ * Active resolution on the Y axis, in pixels.
+ */
+ int yres;
+
+ /**
+ * @bpp:
+ *
+ * Bits per pixels for the mode.
+ */
int bpp;
+
+ /**
+ * @refresh:
+ *
+ * Refresh rate, in Hertz.
+ */
int refresh;
+
+ /**
+ * @rb:
+ *
+ * Do we need to use reduced blanking?
+ */
bool rb;
+
+ /**
+ * @interlace:
+ *
+ * The mode is interlaced.
+ */
bool interlace;
+
+ /**
+ * @cvt:
+ *
+ * The timings will be calculated using the VESA Coordinated
+ * Video Timings instead of looking up the mode from a table.
+ */
bool cvt;
+
+ /**
+ * @margins:
+ *
+ * Add margins to the mode calculation (1.8% of xres rounded
+ * down to 8 pixels and 1.8% of yres).
+ */
bool margins;
+
+ /**
+ * @force:
+ *
+ * Ignore the hotplug state of the connector, and force its
+ * state to one of the DRM_FORCE_* values.
+ */
enum drm_connector_force force;
+
+ /**
+ * @rotation_reflection:
+ *
+ * Initial rotation and reflection of the mode setup from the
+ * command line. See DRM_MODE_ROTATE_* and
+ * DRM_MODE_REFLECT_*. The only rotations supported are
+ * DRM_MODE_ROTATE_0 and DRM_MODE_ROTATE_180.
+ */
+ unsigned int rotation_reflection;
+
+ /**
+ * @panel_orientation:
+ *
+ * drm-connector "panel orientation" property override value,
+ * DRM_MODE_PANEL_ORIENTATION_UNKNOWN if not set.
+ */
+ enum drm_panel_orientation panel_orientation;
+
+ /**
+ * @tv_margins: TV margins to apply to the mode.
+ */
+ struct drm_connector_tv_margins tv_margins;
};
/**
@@ -846,16 +1189,18 @@ struct drm_connector {
/**
* @ycbcr_420_allowed : This bool indicates if this connector is
* capable of handling YCBCR 420 output. While parsing the EDID
- * blocks, its very helpful to know, if the source is capable of
+ * blocks it's very helpful to know if the source is capable of
* handling YCBCR 420 outputs.
*/
bool ycbcr_420_allowed;
/**
- * @registered: Is this connector exposed (registered) with userspace?
+ * @registration_state: Is this connector initializing, exposed
+ * (registered) with userspace, or unregistered?
+ *
* Protected by @mutex.
*/
- bool registered;
+ enum drm_connector_registration_state registration_state;
/**
* @modes:
@@ -910,10 +1255,21 @@ struct drm_connector {
struct drm_property *scaling_mode_property;
/**
- * @content_protection_property: DRM ENUM property for content
- * protection. See drm_connector_attach_content_protection_property().
+ * @vrr_capable_property: Optional property to help userspace
+ * query hardware support for variable refresh rate on a connector.
+ * connector. Drivers can add the property to a connector by
+ * calling drm_connector_attach_vrr_capable_property().
+ *
+ * This should be updated only by calling
+ * drm_connector_set_vrr_capable_property().
*/
- struct drm_property *content_protection_property;
+ struct drm_property *vrr_capable_property;
+
+ /**
+ * @colorspace_property: Connector property to set the suitable
+ * colorspace supported by the sink.
+ */
+ struct drm_property *colorspace_property;
/**
* @path_blob_ptr:
@@ -923,6 +1279,12 @@ struct drm_connector {
*/
struct drm_property_blob *path_blob_ptr;
+ /**
+ * @max_bpc_property: Default connector property for the max bpc to be
+ * driven out of the connector.
+ */
+ struct drm_property *max_bpc_property;
+
#define DRM_CONNECTOR_POLL_HPD (1 << 0)
#define DRM_CONNECTOR_POLL_CONNECT (1 << 1)
#define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2)
@@ -968,12 +1330,12 @@ struct drm_connector {
/** @override_edid: has the EDID been overwritten through debugfs for testing? */
bool override_edid;
-#define DRM_CONNECTOR_MAX_ENCODER 3
/**
- * @encoder_ids: Valid encoders for this connector. Please only use
- * drm_connector_for_each_possible_encoder() to enumerate these.
+ * @possible_encoders: Bit mask of encoders that can drive this
+ * connector, drm_encoder_index() determines the index into the bitfield
+ * and the bits are set with drm_connector_attach_encoder().
*/
- uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
+ u32 possible_encoders;
/**
* @encoder: Currently bound encoder driving this connector, if any.
@@ -998,6 +1360,18 @@ struct drm_connector {
* [0]: progressive, [1]: interlaced
*/
int audio_latency[2];
+
+ /**
+ * @ddc: associated ddc adapter.
+ * A connector usually has its associated ddc adapter. If a driver uses
+ * this field, then an appropriate symbolic link is created in connector
+ * sysfs directory to make it easy for the user to tell which i2c
+ * adapter is for a particular display.
+ *
+ * The field should be set by calling drm_connector_init_with_ddc().
+ */
+ struct i2c_adapter *ddc;
+
/**
* @null_edid_counter: track sinks that give us all zeros for the EDID.
* Needed to workaround some HW bugs where we get all 0s
@@ -1013,6 +1387,12 @@ struct drm_connector {
* rev1.1 4.2.2.6
*/
bool edid_corrupt;
+ /**
+ * @real_edid_checksum: real edid checksum for corrupted edid block.
+ * Required in Displayport 1.4 compliance testing
+ * rev1.1 4.2.2.6
+ */
+ u8 real_edid_checksum;
/** @debugfs_entry: debugfs directory for this connector */
struct dentry *debugfs_entry;
@@ -1080,6 +1460,9 @@ struct drm_connector {
* &drm_mode_config.connector_free_work.
*/
struct llist_node free_node;
+
+ /** @hdr_sink_metadata: HDR Metadata Information read from sink */
+ struct hdr_sink_metadata hdr_sink_metadata;
};
#define obj_to_connector(x) container_of(x, struct drm_connector, base)
@@ -1088,6 +1471,12 @@ int drm_connector_init(struct drm_device *dev,
struct drm_connector *connector,
const struct drm_connector_funcs *funcs,
int connector_type);
+int drm_connector_init_with_ddc(struct drm_device *dev,
+ struct drm_connector *connector,
+ const struct drm_connector_funcs *funcs,
+ int connector_type,
+ struct i2c_adapter *ddc);
+void drm_connector_attach_edid_property(struct drm_connector *connector);
int drm_connector_register(struct drm_connector *connector);
void drm_connector_unregister(struct drm_connector *connector);
int drm_connector_attach_encoder(struct drm_connector *connector,
@@ -1147,29 +1536,24 @@ static inline void drm_connector_put(struct drm_connector *connector)
}
/**
- * drm_connector_reference - acquire a connector reference
+ * drm_connector_is_unregistered - has the connector been unregistered from
+ * userspace?
* @connector: DRM connector
*
- * This is a compatibility alias for drm_connector_get() and should not be
- * used by new code.
- */
-static inline void drm_connector_reference(struct drm_connector *connector)
-{
- drm_connector_get(connector);
-}
-
-/**
- * drm_connector_unreference - release a connector reference
- * @connector: DRM connector
+ * Checks whether or not @connector has been unregistered from userspace.
*
- * This is a compatibility alias for drm_connector_put() and should not be
- * used by new code.
+ * Returns:
+ * True if the connector was unregistered, false if the connector is
+ * registered or has not yet been registered with userspace.
*/
-static inline void drm_connector_unreference(struct drm_connector *connector)
+static inline bool
+drm_connector_is_unregistered(struct drm_connector *connector)
{
- drm_connector_put(connector);
+ return READ_ONCE(connector->registration_state) ==
+ DRM_CONNECTOR_UNREGISTERED;
}
+const char *drm_get_connector_type_name(unsigned int connector_type);
const char *drm_get_connector_status_name(enum drm_connector_status status);
const char *drm_get_subpixel_order_name(enum subpixel_order order);
const char *drm_get_dpms_name(int val);
@@ -1178,18 +1562,23 @@ const char *drm_get_dvi_i_select_name(int val);
const char *drm_get_tv_subconnector_name(int val);
const char *drm_get_tv_select_name(int val);
const char *drm_get_content_protection_name(int val);
+const char *drm_get_hdcp_content_type_name(int val);
int drm_mode_create_dvi_i_properties(struct drm_device *dev);
+int drm_mode_create_tv_margin_properties(struct drm_device *dev);
int drm_mode_create_tv_properties(struct drm_device *dev,
unsigned int num_modes,
const char * const modes[]);
+void drm_connector_attach_tv_margin_properties(struct drm_connector *conn);
int drm_mode_create_scaling_mode_property(struct drm_device *dev);
int drm_connector_attach_content_type_property(struct drm_connector *dev);
int drm_connector_attach_scaling_mode_property(struct drm_connector *connector,
u32 scaling_mode_mask);
-int drm_connector_attach_content_protection_property(
+int drm_connector_attach_vrr_capable_property(
struct drm_connector *connector);
int drm_mode_create_aspect_ratio_property(struct drm_device *dev);
+int drm_mode_create_hdmi_colorspace_property(struct drm_connector *connector);
+int drm_mode_create_dp_colorspace_property(struct drm_connector *connector);
int drm_mode_create_content_type_property(struct drm_device *dev);
void drm_hdmi_avi_infoframe_content_type(struct hdmi_avi_infoframe *frame,
const struct drm_connector_state *conn_state);
@@ -1203,8 +1592,17 @@ int drm_connector_update_edid_property(struct drm_connector *connector,
const struct edid *edid);
void drm_connector_set_link_status_property(struct drm_connector *connector,
uint64_t link_status);
-int drm_connector_init_panel_orientation_property(
- struct drm_connector *connector, int width, int height);
+void drm_connector_set_vrr_capable_property(
+ struct drm_connector *connector, bool capable);
+int drm_connector_set_panel_orientation(
+ struct drm_connector *connector,
+ enum drm_panel_orientation panel_orientation);
+int drm_connector_set_panel_orientation_with_quirk(
+ struct drm_connector *connector,
+ enum drm_panel_orientation panel_orientation,
+ int width, int height);
+int drm_connector_attach_max_bpc_property(struct drm_connector *connector,
+ int min, int max);
/**
* struct drm_tile_group - Tile group metadata
@@ -1270,13 +1668,9 @@ bool drm_connector_has_possible_encoder(struct drm_connector *connector,
* drm_connector_for_each_possible_encoder - iterate connector's possible encoders
* @connector: &struct drm_connector pointer
* @encoder: &struct drm_encoder pointer used as cursor
- * @__i: int iteration cursor, for macro-internal use
*/
-#define drm_connector_for_each_possible_encoder(connector, encoder, __i) \
- for ((__i) = 0; (__i) < ARRAY_SIZE((connector)->encoder_ids) && \
- (connector)->encoder_ids[(__i)] != 0; (__i)++) \
- for_each_if((encoder) = \
- drm_encoder_find((connector)->dev, NULL, \
- (connector)->encoder_ids[(__i)])) \
+#define drm_connector_for_each_possible_encoder(connector, encoder) \
+ drm_for_each_encoder_mask(encoder, (connector)->dev, \
+ (connector)->possible_encoders)
#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_crtc.h b/sys/dev/pci/drm/include/drm/drm_crtc.h
index 54879c25d5c..59b51a09cae 100644
--- a/sys/dev/pci/drm/include/drm/drm_crtc.h
+++ b/sys/dev/pci/drm/include/drm/drm_crtc.h
@@ -31,10 +31,6 @@
#include <linux/fb.h>
#include <linux/hdmi.h>
#include <linux/media-bus-format.h>
-
-#include <linux/err.h>
-#include <linux/sched.h>
-
#include <uapi/drm/drm_mode.h>
#include <uapi/drm/drm_fourcc.h>
#include <drm/drm_modeset_lock.h>
@@ -43,8 +39,8 @@
#include <drm/drm_framebuffer.h>
#include <drm/drm_modes.h>
#include <drm/drm_connector.h>
+#include <drm/drm_device.h>
#include <drm/drm_property.h>
-#include <drm/drm_bridge.h>
#include <drm/drm_edid.h>
#include <drm/drm_plane.h>
#include <drm/drm_blend.h>
@@ -57,6 +53,7 @@ struct drm_mode_set;
struct drm_file;
struct drm_clip_rect;
struct drm_printer;
+struct drm_self_refresh_data;
struct device_node;
struct dma_fence;
struct edid;
@@ -82,7 +79,7 @@ struct drm_plane_helper_funcs;
/**
* struct drm_crtc_state - mutable CRTC state
*
- * Note that the distinction between @enable and @active is rather subtile:
+ * Note that the distinction between @enable and @active is rather subtle:
* Flipping @active while @enable is set without changing anything else may
* never return in a failure from the &drm_mode_config_funcs.atomic_check
* callback. Userspace assumes that a DPMS On will always succeed. In other
@@ -177,12 +174,25 @@ struct drm_crtc_state {
* @no_vblank:
*
* Reflects the ability of a CRTC to send VBLANK events. This state
- * usually depends on the pipeline configuration, and the main usuage
- * is CRTCs feeding a writeback connector operating in oneshot mode.
- * In this case the VBLANK event is only generated when a job is queued
- * to the writeback connector, and we want the core to fake VBLANK
- * events when this part of the pipeline hasn't changed but others had
- * or when the CRTC and connectors are being disabled.
+ * usually depends on the pipeline configuration. If set to true, DRM
+ * atomic helpers will send out a fake VBLANK event during display
+ * updates after all hardware changes have been committed. This is
+ * implemented in drm_atomic_helper_fake_vblank().
+ *
+ * One usage is for drivers and/or hardware without support for VBLANK
+ * interrupts. Such drivers typically do not initialize vblanking
+ * (i.e., call drm_vblank_init() with the number of CRTCs). For CRTCs
+ * without initialized vblanking, this field is set to true in
+ * drm_atomic_helper_check_modeset(), and a fake VBLANK event will be
+ * send out on each update of the display pipeline by
+ * drm_atomic_helper_fake_vblank().
+ *
+ * Another usage is CRTCs feeding a writeback connector operating in
+ * oneshot mode. In this case the fake VBLANK event is only generated
+ * when a job is queued to the writeback connector, and we want the
+ * core to fake VBLANK events when this part of the pipeline hasn't
+ * changed but others had or when the CRTC and connectors are being
+ * disabled.
*
* __drm_atomic_helper_crtc_duplicate_state() will not reset the value
* from the current state, the CRTC driver is then responsible for
@@ -287,12 +297,32 @@ struct drm_crtc_state {
u32 target_vblank;
/**
- * @pageflip_flags:
+ * @async_flip:
+ *
+ * This is set when DRM_MODE_PAGE_FLIP_ASYNC is set in the legacy
+ * PAGE_FLIP IOCTL. It's not wired up for the atomic IOCTL itself yet.
+ */
+ bool async_flip;
+
+ /**
+ * @vrr_enabled:
*
- * DRM_MODE_PAGE_FLIP_* flags, as passed to the page flip ioctl.
- * Zero in any other case.
+ * Indicates if variable refresh rate should be enabled for the CRTC.
+ * Support for the requested vrr state will depend on driver and
+ * hardware capabiltiy - lacking support is not treated as failure.
*/
- u32 pageflip_flags;
+ bool vrr_enabled;
+
+ /**
+ * @self_refresh_active:
+ *
+ * Used by the self refresh helpers to denote when a self refresh
+ * transition is occurring. This will be set on enable/disable callbacks
+ * when self refresh is being enabled or disabled. In some cases, it may
+ * not be desirable to fully shut off the crtc during self refresh.
+ * CRTC's can inspect this flag and determine the best course of action.
+ */
+ bool self_refresh_active;
/**
* @event:
@@ -318,7 +348,14 @@ struct drm_crtc_state {
* - Events for disabled CRTCs are not allowed, and drivers can ignore
* that case.
*
- * This can be handled by the drm_crtc_send_vblank_event() function,
+ * For very simple hardware without VBLANK interrupt, enabling
+ * &struct drm_crtc_state.no_vblank makes DRM's atomic commit helpers
+ * send a fake VBLANK event at the end of the display update after all
+ * hardware changes have been applied. See
+ * drm_atomic_helper_fake_vblank().
+ *
+ * For more complex hardware this
+ * can be handled by the drm_crtc_send_vblank_event() function,
* which the driver should call on the provided event upon completion of
* the atomic commit. Note that if the driver supports vblank signalling
* and timestamping the vblank counters and timestamps must agree with
@@ -467,7 +504,7 @@ struct drm_crtc_funcs {
/**
* @destroy:
*
- * Clean up plane resources. This is only called at driver unload time
+ * Clean up CRTC resources. This is only called at driver unload time
* through drm_mode_config_cleanup() since a CRTC cannot be hotplugged
* in DRM.
*/
@@ -738,6 +775,9 @@ struct drm_crtc_funcs {
* provided from the configured source. Drivers must accept an "auto"
* source name that will select a default source for this CRTC.
*
+ * This may trigger an atomic modeset commit if necessary, to enable CRC
+ * generation.
+ *
* Note that "auto" can depend upon the current modeset configuration,
* e.g. it could pick an encoder or output specific CRC sampling point.
*
@@ -748,8 +788,46 @@ struct drm_crtc_funcs {
*
* 0 on success or a negative error code on failure.
*/
- int (*set_crc_source)(struct drm_crtc *crtc, const char *source,
- size_t *values_cnt);
+ int (*set_crc_source)(struct drm_crtc *crtc, const char *source);
+
+ /**
+ * @verify_crc_source:
+ *
+ * verifies the source of CRC checksums of frames before setting the
+ * source for CRC and during crc open. Source parameter can be NULL
+ * while disabling crc source.
+ *
+ * This callback is optional if the driver does not support any CRC
+ * generation functionality.
+ *
+ * RETURNS:
+ *
+ * 0 on success or a negative error code on failure.
+ */
+ int (*verify_crc_source)(struct drm_crtc *crtc, const char *source,
+ size_t *values_cnt);
+ /**
+ * @get_crc_sources:
+ *
+ * Driver callback for getting a list of all the available sources for
+ * CRC generation. This callback depends upon verify_crc_source, So
+ * verify_crc_source callback should be implemented before implementing
+ * this. Driver can pass full list of available crc sources, this
+ * callback does the verification on each crc-source before passing it
+ * to userspace.
+ *
+ * This callback is optional if the driver does not support exporting of
+ * possible CRC sources list.
+ *
+ * RETURNS:
+ *
+ * a constant character pointer to the list of all the available CRC
+ * sources. On failure driver should return NULL. count should be
+ * updated with number of sources in list. if zero we don't process any
+ * source from the list.
+ */
+ const char *const *(*get_crc_sources)(struct drm_crtc *crtc,
+ size_t *count);
/**
* @atomic_print_state:
@@ -809,6 +887,47 @@ struct drm_crtc_funcs {
* new drivers as the replacement of &drm_driver.disable_vblank hook.
*/
void (*disable_vblank)(struct drm_crtc *crtc);
+
+ /**
+ * @get_vblank_timestamp:
+ *
+ * Called by drm_get_last_vbltimestamp(). Should return a precise
+ * timestamp when the most recent vblank interval ended or will end.
+ *
+ * Specifically, the timestamp in @vblank_time should correspond as
+ * closely as possible to the time when the first video scanline of
+ * the video frame after the end of vblank will start scanning out,
+ * the time immediately after end of the vblank interval. If the
+ * @crtc is currently inside vblank, this will be a time in the future.
+ * If the @crtc is currently scanning out a frame, this will be the
+ * past start time of the current scanout. This is meant to adhere
+ * to the OpenML OML_sync_control extension specification.
+ *
+ * Parameters:
+ *
+ * crtc:
+ * CRTC for which timestamp should be returned.
+ * max_error:
+ * Maximum allowable timestamp error in nanoseconds.
+ * Implementation should strive to provide timestamp
+ * with an error of at most max_error nanoseconds.
+ * Returns true upper bound on error for timestamp.
+ * vblank_time:
+ * Target location for returned vblank timestamp.
+ * in_vblank_irq:
+ * True when called from drm_crtc_handle_vblank(). Some drivers
+ * need to apply some workarounds for gpu-specific vblank irq quirks
+ * if flag is set.
+ *
+ * Returns:
+ *
+ * True on success, false on failure, which means the core should
+ * fallback to a simple timestamp taken in drm_crtc_handle_vblank().
+ */
+ bool (*get_vblank_timestamp)(struct drm_crtc *crtc,
+ int *max_error,
+ ktime_t *vblank_time,
+ bool in_vblank_irq);
};
/**
@@ -916,11 +1035,12 @@ struct drm_crtc {
* Programmed mode in hw, after adjustments for encoders, crtc, panel
* scaling etc. Should only be used by legacy drivers, for high
* precision vblank timestamps in
- * drm_calc_vbltimestamp_from_scanoutpos().
+ * drm_crtc_vblank_helper_get_vblank_timestamp().
*
* Note that atomic drivers should not use this, but instead use
* &drm_crtc_state.adjusted_mode. And for high-precision timestamps
- * drm_calc_vbltimestamp_from_scanoutpos() used &drm_vblank_crtc.hwmode,
+ * drm_crtc_vblank_helper_get_vblank_timestamp() used
+ * &drm_vblank_crtc.hwmode,
* which is filled out by calling drm_calc_timestamping_constants().
*/
struct drm_display_mode hwmode;
@@ -1045,6 +1165,13 @@ struct drm_crtc {
* The name of the CRTC's fence timeline.
*/
char timeline_name[32];
+
+ /**
+ * @self_refresh_data: Holds the state for the self refresh helpers
+ *
+ * Initialized via drm_self_refresh_helper_init().
+ */
+ struct drm_self_refresh_data *self_refresh_data;
};
/**
@@ -1107,9 +1234,6 @@ static inline uint32_t drm_crtc_mask(const struct drm_crtc *crtc)
return 1 << drm_crtc_index(crtc);
}
-int drm_crtc_force_disable(struct drm_crtc *crtc);
-int drm_crtc_force_disable_all(struct drm_device *dev);
-
int drm_mode_set_config_internal(struct drm_mode_set *set);
struct drm_crtc *drm_crtc_from_index(struct drm_device *dev, int idx);
diff --git a/sys/dev/pci/drm/include/drm/drm_crtc_helper.h b/sys/dev/pci/drm/include/drm/drm_crtc_helper.h
index 6f88d660928..a6d520d5b6c 100644
--- a/sys/dev/pci/drm/include/drm/drm_crtc_helper.h
+++ b/sys/dev/pci/drm/include/drm/drm_crtc_helper.h
@@ -56,29 +56,6 @@ bool drm_helper_encoder_in_use(struct drm_encoder *encoder);
int drm_helper_connector_dpms(struct drm_connector *connector, int mode);
void drm_helper_resume_force_mode(struct drm_device *dev);
-
-int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode, int x, int y,
- struct drm_framebuffer *old_fb);
-int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
- struct drm_framebuffer *old_fb);
-
-/* drm_probe_helper.c */
-int drm_helper_probe_single_connector_modes(struct drm_connector
- *connector, uint32_t maxX,
- uint32_t maxY);
-int drm_helper_probe_detect(struct drm_connector *connector,
- struct drm_modeset_acquire_ctx *ctx,
- bool force);
-void drm_kms_helper_poll_init(struct drm_device *dev);
-void drm_kms_helper_poll_fini(struct drm_device *dev);
-bool drm_helper_hpd_irq_event(struct drm_device *dev);
-void drm_kms_helper_hotplug_event(struct drm_device *dev);
-
-void drm_kms_helper_poll_disable(struct drm_device *dev);
-void drm_kms_helper_poll_enable(struct drm_device *dev);
-#ifdef __linux__
-bool drm_kms_helper_is_poll_worker(void);
-#endif
+int drm_helper_force_disable_all(struct drm_device *dev);
#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_damage_helper.h b/sys/dev/pci/drm/include/drm/drm_damage_helper.h
new file mode 100644
index 00000000000..40c34a5bf14
--- /dev/null
+++ b/sys/dev/pci/drm/include/drm/drm_damage_helper.h
@@ -0,0 +1,102 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/**************************************************************************
+ *
+ * Copyright (c) 2018 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Deepak Rawat <drawat@vmware.com>
+ *
+ **************************************************************************/
+
+#ifndef DRM_DAMAGE_HELPER_H_
+#define DRM_DAMAGE_HELPER_H_
+
+#include <drm/drm_atomic_helper.h>
+
+/**
+ * drm_atomic_for_each_plane_damage - Iterator macro for plane damage.
+ * @iter: The iterator to advance.
+ * @rect: Return a rectangle in fb coordinate clipped to plane src.
+ *
+ * Note that if the first call to iterator macro return false then no need to do
+ * plane update. Iterator will return full plane src when damage is not passed
+ * by user-space.
+ */
+#define drm_atomic_for_each_plane_damage(iter, rect) \
+ while (drm_atomic_helper_damage_iter_next(iter, rect))
+
+/**
+ * struct drm_atomic_helper_damage_iter - Closure structure for damage iterator.
+ *
+ * This structure tracks state needed to walk the list of plane damage clips.
+ */
+struct drm_atomic_helper_damage_iter {
+ /* private: Plane src in whole number. */
+ struct drm_rect plane_src;
+ /* private: Rectangles in plane damage blob. */
+ const struct drm_rect *clips;
+ /* private: Number of rectangles in plane damage blob. */
+ uint32_t num_clips;
+ /* private: Current clip iterator is advancing on. */
+ uint32_t curr_clip;
+ /* private: Whether need full plane update. */
+ bool full_update;
+};
+
+void drm_plane_enable_fb_damage_clips(struct drm_plane *plane);
+void drm_atomic_helper_check_plane_damage(struct drm_atomic_state *state,
+ struct drm_plane_state *plane_state);
+int drm_atomic_helper_dirtyfb(struct drm_framebuffer *fb,
+ struct drm_file *file_priv, unsigned int flags,
+ unsigned int color, struct drm_clip_rect *clips,
+ unsigned int num_clips);
+void
+drm_atomic_helper_damage_iter_init(struct drm_atomic_helper_damage_iter *iter,
+ const struct drm_plane_state *old_state,
+ const struct drm_plane_state *new_state);
+bool
+drm_atomic_helper_damage_iter_next(struct drm_atomic_helper_damage_iter *iter,
+ struct drm_rect *rect);
+bool drm_atomic_helper_damage_merged(const struct drm_plane_state *old_state,
+ struct drm_plane_state *state,
+ struct drm_rect *rect);
+
+/**
+ * drm_helper_get_plane_damage_clips - Returns damage clips in &drm_rect.
+ * @state: Plane state.
+ *
+ * Returns plane damage rectangles in internal &drm_rect. Currently &drm_rect
+ * can be obtained by simply typecasting &drm_mode_rect. This is because both
+ * are signed 32 and during drm_atomic_check_only() it is verified that damage
+ * clips are inside fb.
+ *
+ * Return: Clips in plane fb_damage_clips blob property.
+ */
+static inline struct drm_rect *
+drm_helper_get_plane_damage_clips(const struct drm_plane_state *state)
+{
+ return (struct drm_rect *)drm_plane_get_damage_clips(state);
+}
+
+#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_debugfs.h b/sys/dev/pci/drm/include/drm/drm_debugfs.h
new file mode 100644
index 00000000000..7501e323d38
--- /dev/null
+++ b/sys/dev/pci/drm/include/drm/drm_debugfs.h
@@ -0,0 +1,103 @@
+/*
+ * Internal Header for the Direct Rendering Manager
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * Copyright (c) 2009-2010, Code Aurora Forum.
+ * All rights reserved.
+ *
+ * Author: Rickard E. (Rik) Faith <faith@valinux.com>
+ * Author: Gareth Hughes <gareth@valinux.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DRM_DEBUGFS_H_
+#define _DRM_DEBUGFS_H_
+
+#include <linux/types.h>
+#include <linux/seq_file.h>
+/**
+ * struct drm_info_list - debugfs info list entry
+ *
+ * This structure represents a debugfs file to be created by the drm
+ * core.
+ */
+struct drm_info_list {
+ /** @name: file name */
+ const char *name;
+ /**
+ * @show:
+ *
+ * Show callback. &seq_file->private will be set to the &struct
+ * drm_info_node corresponding to the instance of this info on a given
+ * &struct drm_minor.
+ */
+ int (*show)(struct seq_file*, void*);
+ /** @driver_features: Required driver features for this entry */
+ u32 driver_features;
+ /** @data: Driver-private data, should not be device-specific. */
+ void *data;
+};
+
+/**
+ * struct drm_info_node - Per-minor debugfs node structure
+ *
+ * This structure represents a debugfs file, as an instantiation of a &struct
+ * drm_info_list on a &struct drm_minor.
+ *
+ * FIXME:
+ *
+ * No it doesn't make a hole lot of sense that we duplicate debugfs entries for
+ * both the render and the primary nodes, but that's how this has organically
+ * grown. It should probably be fixed, with a compatibility link, if needed.
+ */
+struct drm_info_node {
+ /** @minor: &struct drm_minor for this node. */
+ struct drm_minor *minor;
+ /** @info_ent: template for this node. */
+ const struct drm_info_list *info_ent;
+ /* private: */
+ struct list_head list;
+ struct dentry *dent;
+};
+
+#if defined(CONFIG_DEBUG_FS)
+int drm_debugfs_create_files(const struct drm_info_list *files,
+ int count, struct dentry *root,
+ struct drm_minor *minor);
+int drm_debugfs_remove_files(const struct drm_info_list *files,
+ int count, struct drm_minor *minor);
+#else
+static inline int drm_debugfs_create_files(const struct drm_info_list *files,
+ int count, struct dentry *root,
+ struct drm_minor *minor)
+{
+ return 0;
+}
+
+static inline int drm_debugfs_remove_files(const struct drm_info_list *files,
+ int count, struct drm_minor *minor)
+{
+ return 0;
+}
+#endif
+
+#endif /* _DRM_DEBUGFS_H_ */
diff --git a/sys/dev/pci/drm/include/drm/drm_device.h b/sys/dev/pci/drm/include/drm/drm_device.h
index 8e2016b6df7..2d3255c3ced 100644
--- a/sys/dev/pci/drm/include/drm/drm_device.h
+++ b/sys/dev/pci/drm/include/drm/drm_device.h
@@ -1,112 +1,256 @@
-/*-
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- *
- */
-
#ifndef _DRM_DEVICE_H_
#define _DRM_DEVICE_H_
+#include <sys/types.h>
+#include <sys/selinfo.h>
+
+#include <linux/list.h>
+#include <linux/kref.h>
+#include <linux/mutex.h>
+#include <linux/idr.h>
+#include <linux/pci.h>
+
#include <drm/drm_hashtab.h>
#include <drm/drm_mode_config.h>
+#include <sys/pool.h>
+
struct drm_driver;
+struct drm_minor;
+struct drm_master;
+struct drm_device_dma;
struct drm_vblank_crtc;
+struct drm_sg_mem;
struct drm_local_map;
struct drm_vma_offset_manager;
+struct drm_vram_mm;
struct drm_fb_helper;
+struct inode;
+
struct pci_dev;
+struct pci_controller;
+
+
+/**
+ * enum drm_switch_power - power state of drm device
+ */
+
+enum switch_power_state {
+ /** @DRM_SWITCH_POWER_ON: Power state is ON */
+ DRM_SWITCH_POWER_ON = 0,
+
+ /** @DRM_SWITCH_POWER_OFF: Power state is OFF */
+ DRM_SWITCH_POWER_OFF = 1,
-/**
- * DRM device functions structure
+ /** @DRM_SWITCH_POWER_CHANGING: Power state is changing */
+ DRM_SWITCH_POWER_CHANGING = 2,
+
+ /** @DRM_SWITCH_POWER_DYNAMIC_OFF: Suspended */
+ DRM_SWITCH_POWER_DYNAMIC_OFF = 3,
+};
+
+/**
+ * struct drm_device - DRM device structure
+ *
+ * This structure represent a complete card that
+ * may contain multiple heads.
*/
struct drm_device {
struct device *dev;
- struct drm_driver *driver;
+ /**
+ * @legacy_dev_list:
+ *
+ * List of devices per driver for stealth attach cleanup
+ */
+ struct list_head legacy_dev_list;
- struct klist note;
+ /** @if_version: Highest interface version set */
+ int if_version;
- struct pci_dev _pdev;
- struct pci_dev *pdev;
+ /** @ref: Object ref-count */
+ struct kref ref;
- bus_dma_tag_t dmat;
- bus_space_tag_t bst;
+#ifdef __linux__
+ /** @dev: Device structure of bus-device */
+ struct device *dev;
+#endif
+
+ /** @driver: DRM driver managing the device */
+ struct drm_driver *driver;
+
+ bus_dma_tag_t dmat;
+ bus_space_tag_t bst;
+
+ struct klist note;
+ struct pci_dev _pdev;
struct mutex quiesce_mtx;
int quiesce;
int quiesce_count;
- char *unique; /* Unique identifier: e.g., busid */
- int unique_len; /* Length of unique field */
-
- int if_version; /* Highest interface version set */
- bool registered;
- /* Locks */
- struct rwlock struct_mutex; /* protects everything else */
+ /**
+ * @dev_private:
+ *
+ * DRM driver private data. Instead of using this pointer it is
+ * recommended that drivers use drm_dev_init() and embed struct
+ * &drm_device in their larger per-device structure.
+ */
+ void *dev_private;
+
+ /** @primary: Primary node */
+ struct drm_minor *primary;
+
+ /** @render: Render node */
+ struct drm_minor *render;
+
+ /**
+ * @registered:
+ *
+ * Internally used by drm_dev_register() and drm_connector_register().
+ */
+ bool registered;
+
+ /**
+ * @master:
+ *
+ * Currently active master for this device.
+ * Protected by &master_mutex
+ */
+ struct drm_master *master;
+
+ /**
+ * @driver_features: per-device driver features
+ *
+ * Drivers can clear specific flags here to disallow
+ * certain features on a per-device basis while still
+ * sharing a single &struct drm_driver instance across
+ * all devices.
+ */
+ u32 driver_features;
+
+ /**
+ * @unplugged:
+ *
+ * Flag to tell if the device has been unplugged.
+ * See drm_dev_enter() and drm_dev_is_unplugged().
+ */
+ bool unplugged;
+
+ /** @anon_inode: inode for private address-space */
+ struct inode *anon_inode;
+
+ /** @unique: Unique name of the device */
+ char *unique;
+
+ /**
+ * @struct_mutex:
+ *
+ * Lock for others (not &drm_minor.master and &drm_file.is_master)
+ */
+ struct rwlock struct_mutex;
+
+ /**
+ * @master_mutex:
+ *
+ * Lock for &drm_minor.master and &drm_file.is_master
+ */
+ struct rwlock master_mutex;
- /* Usage Counters */
- int open_count; /* Outstanding files open */
+ /**
+ * @open_count:
+ *
+ * Usage counter for outstanding files open,
+ * protected by drm_global_mutex
+ */
+ atomic_t open_count;
- /* Authentication */
+ /** @filelist_mutex: Protects @filelist. */
+ struct rwlock filelist_mutex;
+ /**
+ * @filelist:
+ *
+ * List of userspace clients, linked through &drm_file.lhead.
+ */
+#ifdef __linux__
+ struct list_head filelist;
+#else
SPLAY_HEAD(drm_file_tree, drm_file) files;
- drm_magic_t magicid;
+#endif
+
+ /**
+ * @filelist_internal:
+ *
+ * List of open DRM files for in-kernel clients.
+ * Protected by &filelist_mutex.
+ */
+ struct list_head filelist_internal;
+
+ /**
+ * @clientlist_mutex:
+ *
+ * Protects &clientlist access.
+ */
+ struct rwlock clientlist_mutex;
- /* Context support */
+ /**
+ * @clientlist:
+ *
+ * List of in-kernel clients. Protected by &clientlist_mutex.
+ */
+ struct list_head clientlist;
- /** \name VBLANK IRQ support */
- /*@{ */
+ /**
+ * @irq_enabled:
+ *
+ * Indicates that interrupt handling is enabled, specifically vblank
+ * handling. Drivers which don't use drm_irq_install() need to set this
+ * to true manually.
+ */
bool irq_enabled;
- int irq;
- /*
- * At load time, disabling the vblank interrupt won't be allowed since
- * old clients may not call the modeset ioctl and therefore misbehave.
- * Once the modeset ioctl *has* been called though, we can safely
- * disable them when unused.
+ /**
+ * @irq: Used by the drm_irq_install() and drm_irq_unistall() helpers.
*/
- bool vblank_disable_allowed;
+ int irq;
- /*
+ /**
+ * @vblank_disable_immediate:
+ *
* If true, vblank interrupt will be disabled immediately when the
* refcount drops to zero, as opposed to via the vblank disable
* timer.
- * This can be set to true it the hardware has a working vblank
- * counter and the driver uses drm_vblank_on() and drm_vblank_off()
- * appropriately.
+ *
+ * This can be set to true it the hardware has a working vblank counter
+ * with high-precision timestamping (otherwise there are races) and the
+ * driver uses drm_crtc_vblank_on() and drm_crtc_vblank_off()
+ * appropriately. See also @max_vblank_count and
+ * &drm_crtc_funcs.get_vblank_counter.
*/
bool vblank_disable_immediate;
- /* array of size num_crtcs */
+ /**
+ * @vblank:
+ *
+ * Array of vblank tracking structures, one per &struct drm_crtc. For
+ * historical reasons (vblank support predates kernel modesetting) this
+ * is free-standing and not part of &struct drm_crtc itself. It must be
+ * initialized explicitly by calling drm_vblank_init().
+ */
struct drm_vblank_crtc *vblank;
- struct mutex vblank_time_lock; /**< Protects vblank count and time updates during vblank enable/disable */
- struct mutex vbl_lock;
+ /**
+ * @vblank_time_lock:
+ *
+ * Protects vblank count and time updates during vblank enable/disable
+ */
+ spinlock_t vblank_time_lock;
+ /**
+ * @vbl_lock: Top-level vblank references lock, wraps the low-level
+ * @vblank_time_lock.
+ */
+ spinlock_t vbl_lock;
/**
* @max_vblank_count:
@@ -129,43 +273,117 @@ struct drm_device {
*
* If non-zero, &drm_crtc_funcs.get_vblank_counter must be set.
*/
- u32 max_vblank_count; /**< size of vblank counter register */
+ u32 max_vblank_count;
+
+ /** @vblank_event_list: List of vblank events */
+ struct list_head vblank_event_list;
/**
- * List of events
+ * @event_lock:
+ *
+ * Protects @vblank_event_list and event delivery in
+ * general. See drm_send_event() and drm_send_event_locked().
*/
- struct list_head vblank_event_list;
spinlock_t event_lock;
- /*@} */
-
- int *vblank_enabled;
- int *vblank_inmodeset;
- u32 *last_vblank_wait;
+ /** @agp: AGP data */
+ struct drm_agp_head *agp;
- int num_crtcs;
+ /** @pdev: PCI device structure */
+ struct pci_dev *pdev;
- struct drm_agp_head *agp;
- void *dev_private;
- struct address_space *dev_mapping;
- struct drm_local_map *agp_buffer_map;
+#ifdef __alpha__
+ /** @hose: PCI hose, only used on ALPHA platforms. */
+ struct pci_controller *hose;
+#endif
+ /** @num_crtcs: Number of CRTCs on this device */
+ unsigned int num_crtcs;
- struct drm_mode_config mode_config; /* Current mode config */
+ /** @mode_config: Current mode config */
+ struct drm_mode_config mode_config;
- /* GEM info */
- atomic_t obj_count;
- u_int obj_name;
- atomic_t obj_memory;
- struct pool objpl;
+ struct pool objpl;
- /** \name GEM information */
- /*@{ */
+ /** @object_name_lock: GEM information */
struct rwlock object_name_lock;
+
+ /** @object_name_idr: GEM information */
struct idr object_name_idr;
+
+ /** @vma_offset_manager: GEM information */
struct drm_vma_offset_manager *vma_offset_manager;
- /*@} */
+ /** @vram_mm: VRAM MM memory manager */
+ struct drm_vram_mm *vram_mm;
+
+ /**
+ * @switch_power_state:
+ *
+ * Power state of the client.
+ * Used by drivers supporting the switcheroo driver.
+ * The state is maintained in the
+ * &vga_switcheroo_client_ops.set_gpu_state callback
+ */
+ enum switch_power_state switch_power_state;
+
+ /**
+ * @fb_helper:
+ *
+ * Pointer to the fbdev emulation structure.
+ * Set by drm_fb_helper_init() and cleared by drm_fb_helper_fini().
+ */
struct drm_fb_helper *fb_helper;
+
+ /* Everything below here is for legacy driver, never use! */
+ /* private: */
+#if IS_ENABLED(CONFIG_DRM_LEGACY)
+ /* Context handle management - linked list of context handles */
+ struct list_head ctxlist;
+
+ /* Context handle management - mutex for &ctxlist */
+ struct rwlock ctxlist_mutex;
+
+ /* Context handle management */
+ struct idr ctx_idr;
+
+ /* Memory management - linked list of regions */
+ struct list_head maplist;
+
+ /* Memory management - user token hash table for maps */
+ struct drm_open_hash map_hash;
+
+ /* Context handle management - list of vmas (for debugging) */
+ struct list_head vmalist;
+
+ /* Optional pointer for DMA support */
+ struct drm_device_dma *dma;
+
+ /* Context swapping flag */
+ __volatile__ long context_flag;
+
+ /* Last current context */
+ int last_context;
+
+ /* Lock for &buf_use and a few other things. */
+ spinlock_t buf_lock;
+
+ /* Usage counter for buffers in use -- cannot alloc */
+ int buf_use;
+
+ /* Buffer allocation in progress */
+ atomic_t buf_alloc;
+
+ struct {
+ int context;
+ struct drm_hw_lock *lock;
+ } sigdata;
+
+ struct drm_local_map *agp_buffer_map;
+ unsigned int agp_buffer_token;
+
+ /* Scatter gather memory */
+ struct drm_sg_mem *sg;
+#endif
};
#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_dp_helper.h b/sys/dev/pci/drm/include/drm/drm_dp_helper.h
index 47c901faee8..21174aed92b 100644
--- a/sys/dev/pci/drm/include/drm/drm_dp_helper.h
+++ b/sys/dev/pci/drm/include/drm/drm_dp_helper.h
@@ -23,9 +23,9 @@
#ifndef _DRM_DP_HELPER_H_
#define _DRM_DP_HELPER_H_
-#include <linux/types.h>
-#include <linux/i2c.h>
#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/types.h>
/*
* Unless otherwise noted, all values are from the DP 1.1a spec. Note that
@@ -42,6 +42,48 @@
* 1.2 formally includes both eDP and DPI definitions.
*/
+/* MSA (Main Stream Attribute) MISC bits (as MISC1<<8|MISC0) */
+#define DP_MSA_MISC_SYNC_CLOCK (1 << 0)
+#define DP_MSA_MISC_INTERLACE_VTOTAL_EVEN (1 << 8)
+#define DP_MSA_MISC_STEREO_NO_3D (0 << 9)
+#define DP_MSA_MISC_STEREO_PROG_RIGHT_EYE (1 << 9)
+#define DP_MSA_MISC_STEREO_PROG_LEFT_EYE (3 << 9)
+/* bits per component for non-RAW */
+#define DP_MSA_MISC_6_BPC (0 << 5)
+#define DP_MSA_MISC_8_BPC (1 << 5)
+#define DP_MSA_MISC_10_BPC (2 << 5)
+#define DP_MSA_MISC_12_BPC (3 << 5)
+#define DP_MSA_MISC_16_BPC (4 << 5)
+/* bits per component for RAW */
+#define DP_MSA_MISC_RAW_6_BPC (1 << 5)
+#define DP_MSA_MISC_RAW_7_BPC (2 << 5)
+#define DP_MSA_MISC_RAW_8_BPC (3 << 5)
+#define DP_MSA_MISC_RAW_10_BPC (4 << 5)
+#define DP_MSA_MISC_RAW_12_BPC (5 << 5)
+#define DP_MSA_MISC_RAW_14_BPC (6 << 5)
+#define DP_MSA_MISC_RAW_16_BPC (7 << 5)
+/* pixel encoding/colorimetry format */
+#define _DP_MSA_MISC_COLOR(misc1_7, misc0_21, misc0_3, misc0_4) \
+ ((misc1_7) << 15 | (misc0_4) << 4 | (misc0_3) << 3 | ((misc0_21) << 1))
+#define DP_MSA_MISC_COLOR_RGB _DP_MSA_MISC_COLOR(0, 0, 0, 0)
+#define DP_MSA_MISC_COLOR_CEA_RGB _DP_MSA_MISC_COLOR(0, 0, 1, 0)
+#define DP_MSA_MISC_COLOR_RGB_WIDE_FIXED _DP_MSA_MISC_COLOR(0, 3, 0, 0)
+#define DP_MSA_MISC_COLOR_RGB_WIDE_FLOAT _DP_MSA_MISC_COLOR(0, 3, 0, 1)
+#define DP_MSA_MISC_COLOR_Y_ONLY _DP_MSA_MISC_COLOR(1, 0, 0, 0)
+#define DP_MSA_MISC_COLOR_RAW _DP_MSA_MISC_COLOR(1, 1, 0, 0)
+#define DP_MSA_MISC_COLOR_YCBCR_422_BT601 _DP_MSA_MISC_COLOR(0, 1, 1, 0)
+#define DP_MSA_MISC_COLOR_YCBCR_422_BT709 _DP_MSA_MISC_COLOR(0, 1, 1, 1)
+#define DP_MSA_MISC_COLOR_YCBCR_444_BT601 _DP_MSA_MISC_COLOR(0, 2, 1, 0)
+#define DP_MSA_MISC_COLOR_YCBCR_444_BT709 _DP_MSA_MISC_COLOR(0, 2, 1, 1)
+#define DP_MSA_MISC_COLOR_XVYCC_422_BT601 _DP_MSA_MISC_COLOR(0, 1, 0, 0)
+#define DP_MSA_MISC_COLOR_XVYCC_422_BT709 _DP_MSA_MISC_COLOR(0, 1, 0, 1)
+#define DP_MSA_MISC_COLOR_XVYCC_444_BT601 _DP_MSA_MISC_COLOR(0, 2, 0, 0)
+#define DP_MSA_MISC_COLOR_XVYCC_444_BT709 _DP_MSA_MISC_COLOR(0, 2, 0, 1)
+#define DP_MSA_MISC_COLOR_OPRGB _DP_MSA_MISC_COLOR(0, 0, 1, 1)
+#define DP_MSA_MISC_COLOR_DCI_P3 _DP_MSA_MISC_COLOR(0, 3, 1, 0)
+#define DP_MSA_MISC_COLOR_COLOR_PROFILE _DP_MSA_MISC_COLOR(0, 3, 1, 1)
+#define DP_MSA_MISC_COLOR_VSC_SDP (1 << 14)
+
#define DP_AUX_MAX_PAYLOAD_BYTES 16
#define DP_AUX_I2C_WRITE 0x0
@@ -95,6 +137,7 @@
# define DP_DETAILED_CAP_INFO_AVAILABLE (1 << 4) /* DPI */
#define DP_MAIN_LINK_CHANNEL_CODING 0x006
+# define DP_CAP_ANSI_8B10B (1 << 0)
#define DP_DOWN_STREAM_PORT_COUNT 0x007
# define DP_PORT_COUNT_MASK 0x0f
@@ -123,8 +166,9 @@
# define DP_FRAMING_CHANGE_CAP (1 << 1)
# define DP_DPCD_DISPLAY_CONTROL_CAPABLE (1 << 3) /* edp v1.2 or higher */
-#define DP_TRAINING_AUX_RD_INTERVAL 0x00e /* XXX 1.2? */
-# define DP_TRAINING_AUX_RD_MASK 0x7F /* XXX 1.2? */
+#define DP_TRAINING_AUX_RD_INTERVAL 0x00e /* XXX 1.2? */
+# define DP_TRAINING_AUX_RD_MASK 0x7F /* DP 1.3 */
+# define DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT (1 << 7) /* DP 1.3 */
#define DP_ADAPTER_CAP 0x00f /* 1.2 */
# define DP_FORCE_LOAD_SENSE_CAP (1 << 0)
@@ -230,6 +274,8 @@
#define DP_DSC_MAX_BITS_PER_PIXEL_LOW 0x067 /* eDP 1.4 */
#define DP_DSC_MAX_BITS_PER_PIXEL_HI 0x068 /* eDP 1.4 */
+# define DP_DSC_MAX_BITS_PER_PIXEL_HI_MASK (0x3 << 0)
+# define DP_DSC_MAX_BITS_PER_PIXEL_HI_SHIFT 8
#define DP_DSC_DEC_COLOR_FORMAT_CAP 0x069
# define DP_DSC_RGB (1 << 0)
@@ -246,6 +292,7 @@
#define DP_DSC_PEAK_THROUGHPUT 0x06B
# define DP_DSC_THROUGHPUT_MODE_0_MASK (0xf << 0)
# define DP_DSC_THROUGHPUT_MODE_0_SHIFT 0
+# define DP_DSC_THROUGHPUT_MODE_0_UPSUPPORTED 0
# define DP_DSC_THROUGHPUT_MODE_0_340 (1 << 0)
# define DP_DSC_THROUGHPUT_MODE_0_400 (2 << 0)
# define DP_DSC_THROUGHPUT_MODE_0_450 (3 << 0)
@@ -260,8 +307,10 @@
# define DP_DSC_THROUGHPUT_MODE_0_900 (12 << 0)
# define DP_DSC_THROUGHPUT_MODE_0_950 (13 << 0)
# define DP_DSC_THROUGHPUT_MODE_0_1000 (14 << 0)
+# define DP_DSC_THROUGHPUT_MODE_0_170 (15 << 0) /* 1.4a */
# define DP_DSC_THROUGHPUT_MODE_1_MASK (0xf << 4)
# define DP_DSC_THROUGHPUT_MODE_1_SHIFT 4
+# define DP_DSC_THROUGHPUT_MODE_1_UPSUPPORTED 0
# define DP_DSC_THROUGHPUT_MODE_1_340 (1 << 4)
# define DP_DSC_THROUGHPUT_MODE_1_400 (2 << 4)
# define DP_DSC_THROUGHPUT_MODE_1_450 (3 << 4)
@@ -276,8 +325,11 @@
# define DP_DSC_THROUGHPUT_MODE_1_900 (12 << 4)
# define DP_DSC_THROUGHPUT_MODE_1_950 (13 << 4)
# define DP_DSC_THROUGHPUT_MODE_1_1000 (14 << 4)
+# define DP_DSC_THROUGHPUT_MODE_1_170 (15 << 4)
#define DP_DSC_MAX_SLICE_WIDTH 0x06C
+#define DP_DSC_MIN_SLICE_WIDTH_VALUE 2560
+#define DP_DSC_SLICE_WIDTH_MULTIPLIER 320
#define DP_DSC_SLICE_CAP_2 0x06D
# define DP_DSC_16_PER_DP_DSC_SINK (1 << 0)
@@ -309,6 +361,10 @@
# define DP_PSR_SETUP_TIME_SHIFT 1
# define DP_PSR2_SU_Y_COORDINATE_REQUIRED (1 << 4) /* eDP 1.4a */
# define DP_PSR2_SU_GRANULARITY_REQUIRED (1 << 5) /* eDP 1.4b */
+
+#define DP_PSR2_SU_X_GRANULARITY 0x072 /* eDP 1.4b */
+#define DP_PSR2_SU_Y_GRANULARITY 0x074 /* eDP 1.4b */
+
/*
* 0x80-0x8f describe downstream port capabilities, but there are two layouts
* based on whether DP_DETAILED_CAP_INFO_AVAILABLE was set. If it was not,
@@ -336,6 +392,8 @@
# define DP_DS_12BPC 2
# define DP_DS_16BPC 3
+#define DP_MAX_DOWNSTREAM_PORTS 0x10
+
/* DP Forward error Correction Registers */
#define DP_FEC_CAPABILITY 0x090 /* 1.4 */
# define DP_FEC_CAPABLE (1 << 0)
@@ -343,6 +401,11 @@
# define DP_FEC_CORR_BLK_ERROR_COUNT_CAP (1 << 2)
# define DP_FEC_BIT_ERROR_COUNT_CAP (1 << 3)
+/* DP Extended DSC Capabilities */
+#define DP_DSC_BRANCH_OVERALL_THROUGHPUT_0 0x0a0 /* DP 1.4a SCR */
+#define DP_DSC_BRANCH_OVERALL_THROUGHPUT_1 0x0a1
+#define DP_DSC_BRANCH_MAX_LINE_WIDTH 0x0a2
+
/* link configuration */
#define DP_LINK_BW_SET 0x100
# define DP_LINK_RATE_TABLE 0x00 /* eDP 1.4 */
@@ -476,6 +539,7 @@
# define DP_AUX_FRAME_SYNC_VALID (1 << 0)
#define DP_DSC_ENABLE 0x160 /* DP 1.4 */
+# define DP_DECOMPRESSION_EN (1 << 0)
#define DP_PSR_EN_CFG 0x170 /* XXX 1.2? */
# define DP_PSR_ENABLE (1 << 0)
@@ -543,6 +607,14 @@
# define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6
#define DP_ADJUST_REQUEST_POST_CURSOR2 0x20c
+# define DP_ADJUST_POST_CURSOR2_LANE0_MASK 0x03
+# define DP_ADJUST_POST_CURSOR2_LANE0_SHIFT 0
+# define DP_ADJUST_POST_CURSOR2_LANE1_MASK 0x0c
+# define DP_ADJUST_POST_CURSOR2_LANE1_SHIFT 2
+# define DP_ADJUST_POST_CURSOR2_LANE2_MASK 0x30
+# define DP_ADJUST_POST_CURSOR2_LANE2_SHIFT 4
+# define DP_ADJUST_POST_CURSOR2_LANE3_MASK 0xc0
+# define DP_ADJUST_POST_CURSOR2_LANE3_SHIFT 6
#define DP_TEST_REQUEST 0x218
# define DP_TEST_LINK_TRAINING (1 << 0)
@@ -550,6 +622,8 @@
# define DP_TEST_LINK_EDID_READ (1 << 2)
# define DP_TEST_LINK_PHY_TEST_PATTERN (1 << 3) /* DPCD >= 1.1 */
# define DP_TEST_LINK_FAUX_PATTERN (1 << 4) /* DPCD >= 1.2 */
+# define DP_TEST_LINK_AUDIO_PATTERN (1 << 5) /* DPCD >= 1.2 */
+# define DP_TEST_LINK_AUDIO_DISABLED_VIDEO (1 << 6) /* DPCD >= 1.2 */
#define DP_TEST_LINK_RATE 0x219
# define DP_LINK_RATE_162 (0x6)
@@ -598,6 +672,7 @@
# define DP_COLOR_FORMAT_RGB (0 << 1)
# define DP_COLOR_FORMAT_YCbCr422 (1 << 1)
# define DP_COLOR_FORMAT_YCbCr444 (2 << 1)
+# define DP_TEST_DYNAMIC_RANGE_VESA (0 << 3)
# define DP_TEST_DYNAMIC_RANGE_CEA (1 << 3)
# define DP_TEST_YCBCR_COEFFICIENTS (1 << 4)
# define DP_YCBCR_COEFFICIENTS_ITU601 (0 << 4)
@@ -647,6 +722,16 @@
#define DP_TEST_SINK 0x270
# define DP_TEST_SINK_START (1 << 0)
+#define DP_TEST_AUDIO_MODE 0x271
+#define DP_TEST_AUDIO_PATTERN_TYPE 0x272
+#define DP_TEST_AUDIO_PERIOD_CH1 0x273
+#define DP_TEST_AUDIO_PERIOD_CH2 0x274
+#define DP_TEST_AUDIO_PERIOD_CH3 0x275
+#define DP_TEST_AUDIO_PERIOD_CH4 0x276
+#define DP_TEST_AUDIO_PERIOD_CH5 0x277
+#define DP_TEST_AUDIO_PERIOD_CH6 0x278
+#define DP_TEST_AUDIO_PERIOD_CH7 0x279
+#define DP_TEST_AUDIO_PERIOD_CH8 0x27A
#define DP_FEC_STATUS 0x280 /* 1.4 */
# define DP_FEC_DECODE_EN_DETECTED (1 << 0)
@@ -684,6 +769,8 @@
# define DP_EDP_12 0x01
# define DP_EDP_13 0x02
# define DP_EDP_14 0x03
+# define DP_EDP_14a 0x04 /* eDP 1.4a */
+# define DP_EDP_14b 0x05 /* eDP 1.4b */
#define DP_EDP_GENERAL_CAP_1 0x701
# define DP_EDP_TCON_BACKLIGHT_ADJUSTMENT_CAP (1 << 0)
@@ -904,6 +991,89 @@
#define DP_AUX_HDCP_KSV_FIFO 0x6802C
#define DP_AUX_HDCP_AINFO 0x6803B
+/* DP HDCP2.2 parameter offsets in DPCD address space */
+#define DP_HDCP_2_2_REG_RTX_OFFSET 0x69000
+#define DP_HDCP_2_2_REG_TXCAPS_OFFSET 0x69008
+#define DP_HDCP_2_2_REG_CERT_RX_OFFSET 0x6900B
+#define DP_HDCP_2_2_REG_RRX_OFFSET 0x69215
+#define DP_HDCP_2_2_REG_RX_CAPS_OFFSET 0x6921D
+#define DP_HDCP_2_2_REG_EKPUB_KM_OFFSET 0x69220
+#define DP_HDCP_2_2_REG_EKH_KM_WR_OFFSET 0x692A0
+#define DP_HDCP_2_2_REG_M_OFFSET 0x692B0
+#define DP_HDCP_2_2_REG_HPRIME_OFFSET 0x692C0
+#define DP_HDCP_2_2_REG_EKH_KM_RD_OFFSET 0x692E0
+#define DP_HDCP_2_2_REG_RN_OFFSET 0x692F0
+#define DP_HDCP_2_2_REG_LPRIME_OFFSET 0x692F8
+#define DP_HDCP_2_2_REG_EDKEY_KS_OFFSET 0x69318
+#define DP_HDCP_2_2_REG_RIV_OFFSET 0x69328
+#define DP_HDCP_2_2_REG_RXINFO_OFFSET 0x69330
+#define DP_HDCP_2_2_REG_SEQ_NUM_V_OFFSET 0x69332
+#define DP_HDCP_2_2_REG_VPRIME_OFFSET 0x69335
+#define DP_HDCP_2_2_REG_RECV_ID_LIST_OFFSET 0x69345
+#define DP_HDCP_2_2_REG_V_OFFSET 0x693E0
+#define DP_HDCP_2_2_REG_SEQ_NUM_M_OFFSET 0x693F0
+#define DP_HDCP_2_2_REG_K_OFFSET 0x693F3
+#define DP_HDCP_2_2_REG_STREAM_ID_TYPE_OFFSET 0x693F5
+#define DP_HDCP_2_2_REG_MPRIME_OFFSET 0x69473
+#define DP_HDCP_2_2_REG_RXSTATUS_OFFSET 0x69493
+#define DP_HDCP_2_2_REG_STREAM_TYPE_OFFSET 0x69494
+#define DP_HDCP_2_2_REG_DBG_OFFSET 0x69518
+
+/* Link Training (LT)-tunable PHY Repeaters */
+#define DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV 0xf0000 /* 1.3 */
+#define DP_MAX_LINK_RATE_PHY_REPEATER 0xf0001 /* 1.4a */
+#define DP_PHY_REPEATER_CNT 0xf0002 /* 1.3 */
+#define DP_PHY_REPEATER_MODE 0xf0003 /* 1.3 */
+#define DP_MAX_LANE_COUNT_PHY_REPEATER 0xf0004 /* 1.4a */
+#define DP_Repeater_FEC_CAPABILITY 0xf0004 /* 1.4 */
+#define DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT 0xf0005 /* 1.4a */
+#define DP_TRAINING_PATTERN_SET_PHY_REPEATER1 0xf0010 /* 1.3 */
+#define DP_TRAINING_LANE0_SET_PHY_REPEATER1 0xf0011 /* 1.3 */
+#define DP_TRAINING_LANE1_SET_PHY_REPEATER1 0xf0012 /* 1.3 */
+#define DP_TRAINING_LANE2_SET_PHY_REPEATER1 0xf0013 /* 1.3 */
+#define DP_TRAINING_LANE3_SET_PHY_REPEATER1 0xf0014 /* 1.3 */
+#define DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1 0xf0020 /* 1.4a */
+#define DP_TRANSMITTER_CAPABILITY_PHY_REPEATER1 0xf0021 /* 1.4a */
+#define DP_LANE0_1_STATUS_PHY_REPEATER1 0xf0030 /* 1.3 */
+#define DP_LANE2_3_STATUS_PHY_REPEATER1 0xf0031 /* 1.3 */
+#define DP_LANE_ALIGN_STATUS_UPDATED_PHY_REPEATER1 0xf0032 /* 1.3 */
+#define DP_ADJUST_REQUEST_LANE0_1_PHY_REPEATER1 0xf0033 /* 1.3 */
+#define DP_ADJUST_REQUEST_LANE2_3_PHY_REPEATER1 0xf0034 /* 1.3 */
+#define DP_SYMBOL_ERROR_COUNT_LANE0_PHY_REPEATER1 0xf0035 /* 1.3 */
+#define DP_SYMBOL_ERROR_COUNT_LANE1_PHY_REPEATER1 0xf0037 /* 1.3 */
+#define DP_SYMBOL_ERROR_COUNT_LANE2_PHY_REPEATER1 0xf0039 /* 1.3 */
+#define DP_SYMBOL_ERROR_COUNT_LANE3_PHY_REPEATER1 0xf003b /* 1.3 */
+#define DP_FEC_STATUS_PHY_REPEATER1 0xf0290 /* 1.4 */
+#define DP_FEC_ERROR_COUNT_PHY_REPEATER1 0xf0291 /* 1.4 */
+#define DP_FEC_CAPABILITY_PHY_REPEATER1 0xf0294 /* 1.4a */
+
+/* Repeater modes */
+#define DP_PHY_REPEATER_MODE_TRANSPARENT 0x55 /* 1.3 */
+#define DP_PHY_REPEATER_MODE_NON_TRANSPARENT 0xaa /* 1.3 */
+
+/* DP HDCP message start offsets in DPCD address space */
+#define DP_HDCP_2_2_AKE_INIT_OFFSET DP_HDCP_2_2_REG_RTX_OFFSET
+#define DP_HDCP_2_2_AKE_SEND_CERT_OFFSET DP_HDCP_2_2_REG_CERT_RX_OFFSET
+#define DP_HDCP_2_2_AKE_NO_STORED_KM_OFFSET DP_HDCP_2_2_REG_EKPUB_KM_OFFSET
+#define DP_HDCP_2_2_AKE_STORED_KM_OFFSET DP_HDCP_2_2_REG_EKH_KM_WR_OFFSET
+#define DP_HDCP_2_2_AKE_SEND_HPRIME_OFFSET DP_HDCP_2_2_REG_HPRIME_OFFSET
+#define DP_HDCP_2_2_AKE_SEND_PAIRING_INFO_OFFSET \
+ DP_HDCP_2_2_REG_EKH_KM_RD_OFFSET
+#define DP_HDCP_2_2_LC_INIT_OFFSET DP_HDCP_2_2_REG_RN_OFFSET
+#define DP_HDCP_2_2_LC_SEND_LPRIME_OFFSET DP_HDCP_2_2_REG_LPRIME_OFFSET
+#define DP_HDCP_2_2_SKE_SEND_EKS_OFFSET DP_HDCP_2_2_REG_EDKEY_KS_OFFSET
+#define DP_HDCP_2_2_REP_SEND_RECVID_LIST_OFFSET DP_HDCP_2_2_REG_RXINFO_OFFSET
+#define DP_HDCP_2_2_REP_SEND_ACK_OFFSET DP_HDCP_2_2_REG_V_OFFSET
+#define DP_HDCP_2_2_REP_STREAM_MANAGE_OFFSET DP_HDCP_2_2_REG_SEQ_NUM_M_OFFSET
+#define DP_HDCP_2_2_REP_STREAM_READY_OFFSET DP_HDCP_2_2_REG_MPRIME_OFFSET
+
+#define HDCP_2_2_DP_RXSTATUS_LEN 1
+#define HDCP_2_2_DP_RXSTATUS_READY(x) ((x) & BIT(0))
+#define HDCP_2_2_DP_RXSTATUS_H_PRIME(x) ((x) & BIT(1))
+#define HDCP_2_2_DP_RXSTATUS_PAIRING(x) ((x) & BIT(2))
+#define HDCP_2_2_DP_RXSTATUS_REAUTH_REQ(x) ((x) & BIT(3))
+#define HDCP_2_2_DP_RXSTATUS_LINK_FAILED(x) ((x) & BIT(4))
+
/* DP 1.2 Sideband message defines */
/* peer device type - DP 1.2a Table 2-92 */
#define DP_PEER_DEVICE_NONE 0x0
@@ -913,6 +1083,7 @@
#define DP_PEER_DEVICE_DP_LEGACY_CONV 0x4
/* DP 1.2 MST sideband request names DP 1.2a Table 2-80 */
+#define DP_GET_MSG_TRANSACTION_VERSION 0x00 /* DP 1.3 */
#define DP_LINK_ADDRESS 0x01
#define DP_CONNECTION_STATUS_NOTIFY 0x02
#define DP_ENUM_PATH_RESOURCES 0x10
@@ -929,6 +1100,10 @@
#define DP_SINK_EVENT_NOTIFY 0x30
#define DP_QUERY_STREAM_ENC_STATUS 0x38
+/* DP 1.2 MST sideband reply types */
+#define DP_SIDEBAND_REPLY_ACK 0x00
+#define DP_SIDEBAND_REPLY_NAK 0x01
+
/* DP 1.2 MST sideband nak reasons - table 2.84 */
#define DP_NAK_WRITE_FAILURE 0x01
#define DP_NAK_INVALID_READ 0x02
@@ -959,9 +1134,12 @@ u8 drm_dp_get_adjust_request_voltage(const u8 link_status[DP_LINK_STATUS_SIZE],
int lane);
u8 drm_dp_get_adjust_request_pre_emphasis(const u8 link_status[DP_LINK_STATUS_SIZE],
int lane);
+u8 drm_dp_get_adjust_request_post_cursor(const u8 link_status[DP_LINK_STATUS_SIZE],
+ unsigned int lane);
#define DP_BRANCH_OUI_HEADER_SIZE 0xc
#define DP_RECEIVER_CAP_SIZE 0xf
+#define DP_DSC_RECEIVER_CAP_SIZE 0xf
#define EDP_PSR_RECEIVER_CAP_SIZE 2
#define EDP_DISPLAY_CTL_CAP_SIZE 3
@@ -983,27 +1161,48 @@ int drm_dp_bw_code_to_link_rate(u8 link_bw);
#define DP_SDP_VSC_EXT_CEA 0x21 /* DP 1.4 */
/* 0x80+ CEA-861 infoframe types */
+/**
+ * struct dp_sdp_header - DP secondary data packet header
+ * @HB0: Secondary Data Packet ID
+ * @HB1: Secondary Data Packet Type
+ * @HB2: Secondary Data Packet Specific header, Byte 0
+ * @HB3: Secondary Data packet Specific header, Byte 1
+ */
struct dp_sdp_header {
- u8 HB0; /* Secondary Data Packet ID */
- u8 HB1; /* Secondary Data Packet Type */
- u8 HB2; /* Secondary Data Packet Specific header, Byte 0 */
- u8 HB3; /* Secondary Data packet Specific header, Byte 1 */
+ u8 HB0;
+ u8 HB1;
+ u8 HB2;
+ u8 HB3;
} __packed;
#define EDP_SDP_HEADER_REVISION_MASK 0x1F
#define EDP_SDP_HEADER_VALID_PAYLOAD_BYTES 0x1F
+#define DP_SDP_PPS_HEADER_PAYLOAD_BYTES_MINUS_1 0x7F
-struct edp_vsc_psr {
+/**
+ * struct dp_sdp - DP secondary data packet
+ * @sdp_header: DP secondary data packet header
+ * @db: DP secondaray data packet data blocks
+ * VSC SDP Payload for PSR
+ * db[0]: Stereo Interface
+ * db[1]: 0 - PSR State; 1 - Update RFB; 2 - CRC Valid
+ * db[2]: CRC value bits 7:0 of the R or Cr component
+ * db[3]: CRC value bits 15:8 of the R or Cr component
+ * db[4]: CRC value bits 7:0 of the G or Y component
+ * db[5]: CRC value bits 15:8 of the G or Y component
+ * db[6]: CRC value bits 7:0 of the B or Cb component
+ * db[7]: CRC value bits 15:8 of the B or Cb component
+ * db[8] - db[31]: Reserved
+ * VSC SDP Payload for Pixel Encoding/Colorimetry Format
+ * db[0] - db[15]: Reserved
+ * db[16]: Pixel Encoding and Colorimetry Formats
+ * db[17]: Dynamic Range and Component Bit Depth
+ * db[18]: Content Type
+ * db[19] - db[31]: Reserved
+ */
+struct dp_sdp {
struct dp_sdp_header sdp_header;
- u8 DB0; /* Stereo Interface */
- u8 DB1; /* 0 - PSR State; 1 - Update RFB; 2 - CRC Valid */
- u8 DB2; /* CRC value bits 7:0 of the R or Cr component */
- u8 DB3; /* CRC value bits 15:8 of the R or Cr component */
- u8 DB4; /* CRC value bits 7:0 of the G or Y component */
- u8 DB5; /* CRC value bits 15:8 of the G or Y component */
- u8 DB6; /* CRC value bits 7:0 of the B or Cb component */
- u8 DB7; /* CRC value bits 15:8 of the B or Cb component */
- u8 DB8_31[24]; /* Reserved */
+ u8 db[32];
} __packed;
#define EDP_VSC_PSR_STATE_ACTIVE (1<<0)
@@ -1032,6 +1231,13 @@ drm_dp_enhanced_frame_cap(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
}
static inline bool
+drm_dp_fast_training_cap(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
+{
+ return dpcd[DP_DPCD_REV] >= 0x11 &&
+ (dpcd[DP_MAX_DOWNSPREAD] & DP_NO_AUX_HANDSHAKE_LINK_TRAINING);
+}
+
+static inline bool
drm_dp_tps3_supported(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
{
return dpcd[DP_DPCD_REV] >= 0x12 &&
@@ -1058,6 +1264,57 @@ drm_dp_is_branch(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
return dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT;
}
+/* DP/eDP DSC support */
+u8 drm_dp_dsc_sink_max_slice_count(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE],
+ bool is_edp);
+u8 drm_dp_dsc_sink_line_buf_depth(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE]);
+int drm_dp_dsc_sink_supported_input_bpcs(const u8 dsc_dpc[DP_DSC_RECEIVER_CAP_SIZE],
+ u8 dsc_bpc[3]);
+
+static inline bool
+drm_dp_sink_supports_dsc(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE])
+{
+ return dsc_dpcd[DP_DSC_SUPPORT - DP_DSC_SUPPORT] &
+ DP_DSC_DECOMPRESSION_IS_SUPPORTED;
+}
+
+static inline u16
+drm_edp_dsc_sink_output_bpp(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE])
+{
+ return dsc_dpcd[DP_DSC_MAX_BITS_PER_PIXEL_LOW - DP_DSC_SUPPORT] |
+ (dsc_dpcd[DP_DSC_MAX_BITS_PER_PIXEL_HI - DP_DSC_SUPPORT] &
+ DP_DSC_MAX_BITS_PER_PIXEL_HI_MASK <<
+ DP_DSC_MAX_BITS_PER_PIXEL_HI_SHIFT);
+}
+
+static inline u32
+drm_dp_dsc_sink_max_slice_width(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE])
+{
+ /* Max Slicewidth = Number of Pixels * 320 */
+ return dsc_dpcd[DP_DSC_MAX_SLICE_WIDTH - DP_DSC_SUPPORT] *
+ DP_DSC_SLICE_WIDTH_MULTIPLIER;
+}
+
+/* Forward Error Correction Support on DP 1.4 */
+static inline bool
+drm_dp_sink_supports_fec(const u8 fec_capable)
+{
+ return fec_capable & DP_FEC_CAPABLE;
+}
+
+static inline bool
+drm_dp_channel_coding_supported(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
+{
+ return dpcd[DP_MAIN_LINK_CHANNEL_CODING] & DP_CAP_ANSI_8B10B;
+}
+
+static inline bool
+drm_dp_alternate_scrambler_reset_cap(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
+{
+ return dpcd[DP_EDP_CONFIGURATION_CAP] &
+ DP_ALTERNATE_SCRAMBLER_RESET_CAP;
+}
+
/*
* DisplayPort AUX channel
*/
@@ -1080,20 +1337,19 @@ struct drm_dp_aux_msg {
struct cec_adapter;
struct edid;
+struct drm_connector;
/**
* struct drm_dp_aux_cec - DisplayPort CEC-Tunneling-over-AUX
* @lock: mutex protecting this struct
* @adap: the CEC adapter for CEC-Tunneling-over-AUX support.
- * @name: name of the CEC adapter
- * @parent: parent device of the CEC adapter
+ * @connector: the connector this CEC adapter is associated with
* @unregister_work: unregister the CEC adapter
*/
struct drm_dp_aux_cec {
struct rwlock lock;
struct cec_adapter *adap;
- const char *name;
- struct device *parent;
+ struct drm_connector *connector;
struct delayed_work unregister_work;
};
@@ -1159,6 +1415,10 @@ struct drm_dp_aux {
* @cec: struct containing fields used for CEC-Tunneling-over-AUX.
*/
struct drm_dp_aux_cec cec;
+ /**
+ * @is_remote: Is this AUX CH actually using sideband messaging.
+ */
+ bool is_remote;
};
ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset,
@@ -1199,22 +1459,9 @@ static inline ssize_t drm_dp_dpcd_writeb(struct drm_dp_aux *aux,
int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
u8 status[DP_LINK_STATUS_SIZE]);
-/*
- * DisplayPort link
- */
-#define DP_LINK_CAP_ENHANCED_FRAMING (1 << 0)
-
-struct drm_dp_link {
- unsigned char revision;
- unsigned int rate;
- unsigned int num_lanes;
- unsigned long capabilities;
-};
+bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux,
+ u8 real_edid_checksum);
-int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link);
-int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link);
-int drm_dp_link_power_down(struct drm_dp_aux *aux, struct drm_dp_link *link);
-int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link);
int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
const u8 port_cap[4]);
int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
@@ -1223,6 +1470,7 @@ int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]);
void drm_dp_downstream_debug(struct seq_file *m, const u8 dpcd[DP_RECEIVER_CAP_SIZE],
const u8 port_cap[4], struct drm_dp_aux *aux);
+void drm_dp_remote_aux_init(struct drm_dp_aux *aux);
void drm_dp_aux_init(struct drm_dp_aux *aux);
int drm_dp_aux_register(struct drm_dp_aux *aux);
void drm_dp_aux_unregister(struct drm_dp_aux *aux);
@@ -1250,41 +1498,77 @@ struct drm_dp_desc {
int drm_dp_read_desc(struct drm_dp_aux *aux, struct drm_dp_desc *desc,
bool is_branch);
+u32 drm_dp_get_edid_quirks(const struct edid *edid);
/**
* enum drm_dp_quirk - Display Port sink/branch device specific quirks
*
* Display Port sink and branch devices in the wild have a variety of bugs, try
* to collect them here. The quirks are shared, but it's up to the drivers to
- * implement workarounds for them.
+ * implement workarounds for them. Note that because some devices have
+ * unreliable OUIDs, the EDID of sinks should also be checked for quirks using
+ * drm_dp_get_edid_quirks().
*/
enum drm_dp_quirk {
/**
- * @DP_DPCD_QUIRK_LIMITED_M_N:
+ * @DP_DPCD_QUIRK_CONSTANT_N:
*
* The device requires main link attributes Mvid and Nvid to be limited
- * to 16 bits.
+ * to 16 bits. So will give a constant value (0x8000) for compatability.
+ */
+ DP_DPCD_QUIRK_CONSTANT_N,
+ /**
+ * @DP_DPCD_QUIRK_NO_PSR:
+ *
+ * The device does not support PSR even if reports that it supports or
+ * driver still need to implement proper handling for such device.
+ */
+ DP_DPCD_QUIRK_NO_PSR,
+ /**
+ * @DP_DPCD_QUIRK_NO_SINK_COUNT:
+ *
+ * The device does not set SINK_COUNT to a non-zero value.
+ * The driver should ignore SINK_COUNT during detection.
+ */
+ DP_DPCD_QUIRK_NO_SINK_COUNT,
+ /**
+ * @DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD:
+ *
+ * The device supports MST DSC despite not supporting Virtual DPCD.
+ * The DSC caps can be read from the physical aux instead.
+ */
+ DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD,
+ /**
+ * @DP_QUIRK_FORCE_DPCD_BACKLIGHT:
+ *
+ * The device is telling the truth when it says that it uses DPCD
+ * backlight controls, even if the system's firmware disagrees. This
+ * quirk should be checked against both the ident and panel EDID.
+ * When present, the driver should honor the DPCD backlight
+ * capabilities advertised.
*/
- DP_DPCD_QUIRK_LIMITED_M_N,
+ DP_QUIRK_FORCE_DPCD_BACKLIGHT,
};
/**
* drm_dp_has_quirk() - does the DP device have a specific quirk
* @desc: Device decriptor filled by drm_dp_read_desc()
+ * @edid_quirks: Optional quirk bitmask filled by drm_dp_get_edid_quirks()
* @quirk: Quirk to query for
*
* Return true if DP device identified by @desc has @quirk.
*/
static inline bool
-drm_dp_has_quirk(const struct drm_dp_desc *desc, enum drm_dp_quirk quirk)
+drm_dp_has_quirk(const struct drm_dp_desc *desc, u32 edid_quirks,
+ enum drm_dp_quirk quirk)
{
- return desc->quirks & BIT(quirk);
+ return (desc->quirks | edid_quirks) & BIT(quirk);
}
#ifdef CONFIG_DRM_DP_CEC
void drm_dp_cec_irq(struct drm_dp_aux *aux);
-void drm_dp_cec_register_connector(struct drm_dp_aux *aux, const char *name,
- struct device *parent);
+void drm_dp_cec_register_connector(struct drm_dp_aux *aux,
+ struct drm_connector *connector);
void drm_dp_cec_unregister_connector(struct drm_dp_aux *aux);
void drm_dp_cec_set_edid(struct drm_dp_aux *aux, const struct edid *edid);
void drm_dp_cec_unset_edid(struct drm_dp_aux *aux);
@@ -1293,9 +1577,9 @@ static inline void drm_dp_cec_irq(struct drm_dp_aux *aux)
{
}
-static inline void drm_dp_cec_register_connector(struct drm_dp_aux *aux,
- const char *name,
- struct device *parent)
+static inline void
+drm_dp_cec_register_connector(struct drm_dp_aux *aux,
+ struct drm_connector *connector)
{
}
diff --git a/sys/dev/pci/drm/include/drm/drm_dp_mst_helper.h b/sys/dev/pci/drm/include/drm/drm_dp_mst_helper.h
index 4070429fb32..cc5cf0649aa 100644
--- a/sys/dev/pci/drm/include/drm/drm_dp_mst_helper.h
+++ b/sys/dev/pci/drm/include/drm/drm_dp_mst_helper.h
@@ -26,6 +26,26 @@
#include <drm/drm_dp_helper.h>
#include <drm/drm_atomic.h>
+#if IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS)
+#include <linux/stackdepot.h>
+#include <linux/timekeeping.h>
+
+enum drm_dp_mst_topology_ref_type {
+ DRM_DP_MST_TOPOLOGY_REF_GET,
+ DRM_DP_MST_TOPOLOGY_REF_PUT,
+};
+
+struct drm_dp_mst_topology_ref_history {
+ struct drm_dp_mst_topology_ref_entry {
+ enum drm_dp_mst_topology_ref_type type;
+ int count;
+ ktime_t ts_nsec;
+ depot_stack_handle_t backtrace;
+ } *entries;
+ int len;
+};
+#endif /* IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS) */
+
struct drm_dp_mst_branch;
/**
@@ -44,30 +64,58 @@ struct drm_dp_vcpi {
/**
* struct drm_dp_mst_port - MST port
- * @kref: reference count for this port.
* @port_num: port number
- * @input: if this port is an input port.
- * @mcs: message capability status - DP 1.2 spec.
- * @ddps: DisplayPort Device Plug Status - DP 1.2
- * @pdt: Peer Device Type
- * @ldps: Legacy Device Plug Status
- * @dpcd_rev: DPCD revision of device on this port
- * @num_sdp_streams: Number of simultaneous streams
- * @num_sdp_stream_sinks: Number of stream sinks
- * @available_pbn: Available bandwidth for this port.
+ * @input: if this port is an input port. Protected by
+ * &drm_dp_mst_topology_mgr.base.lock.
+ * @mcs: message capability status - DP 1.2 spec. Protected by
+ * &drm_dp_mst_topology_mgr.base.lock.
+ * @ddps: DisplayPort Device Plug Status - DP 1.2. Protected by
+ * &drm_dp_mst_topology_mgr.base.lock.
+ * @pdt: Peer Device Type. Protected by
+ * &drm_dp_mst_topology_mgr.base.lock.
+ * @ldps: Legacy Device Plug Status. Protected by
+ * &drm_dp_mst_topology_mgr.base.lock.
+ * @dpcd_rev: DPCD revision of device on this port. Protected by
+ * &drm_dp_mst_topology_mgr.base.lock.
+ * @num_sdp_streams: Number of simultaneous streams. Protected by
+ * &drm_dp_mst_topology_mgr.base.lock.
+ * @num_sdp_stream_sinks: Number of stream sinks. Protected by
+ * &drm_dp_mst_topology_mgr.base.lock.
+ * @full_pbn: Max possible bandwidth for this port. Protected by
+ * &drm_dp_mst_topology_mgr.base.lock.
* @next: link to next port on this branch device
- * @mstb: branch device attach below this port
- * @aux: i2c aux transport to talk to device connected to this port.
+ * @aux: i2c aux transport to talk to device connected to this port, protected
+ * by &drm_dp_mst_topology_mgr.base.lock.
* @parent: branch device parent of this port
* @vcpi: Virtual Channel Payload info for this port.
- * @connector: DRM connector this port is connected to.
+ * @connector: DRM connector this port is connected to. Protected by
+ * &drm_dp_mst_topology_mgr.base.lock.
* @mgr: topology manager this port lives under.
*
* This structure represents an MST port endpoint on a device somewhere
* in the MST topology.
*/
struct drm_dp_mst_port {
- struct kref kref;
+ /**
+ * @topology_kref: refcount for this port's lifetime in the topology,
+ * only the DP MST helpers should need to touch this
+ */
+ struct kref topology_kref;
+
+ /**
+ * @malloc_kref: refcount for the memory allocation containing this
+ * structure. See drm_dp_mst_get_port_malloc() and
+ * drm_dp_mst_put_port_malloc().
+ */
+ struct kref malloc_kref;
+
+#if IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS)
+ /**
+ * @topology_ref_history: A history of each topology
+ * reference/dereference. See CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS.
+ */
+ struct drm_dp_mst_topology_ref_history topology_ref_history;
+#endif
u8 port_num;
bool input;
@@ -78,9 +126,19 @@ struct drm_dp_mst_port {
u8 dpcd_rev;
u8 num_sdp_streams;
u8 num_sdp_stream_sinks;
- uint16_t available_pbn;
+ uint16_t full_pbn;
struct list_head next;
- struct drm_dp_mst_branch *mstb; /* pointer to an mstb if this port has one */
+ /**
+ * @mstb: the branch device connected to this port, if there is one.
+ * This should be considered protected for reading by
+ * &drm_dp_mst_topology_mgr.lock. There are two exceptions to this:
+ * &drm_dp_mst_topology_mgr.up_req_work and
+ * &drm_dp_mst_topology_mgr.work, which do not grab
+ * &drm_dp_mst_topology_mgr.lock during reads but are the only
+ * updaters of this list and are protected from writing concurrently
+ * by &drm_dp_mst_topology_mgr.probe_lock.
+ */
+ struct drm_dp_mst_branch *mstb;
struct drm_dp_aux aux; /* i2c bus for this port? */
struct drm_dp_mst_branch *parent;
@@ -98,16 +156,16 @@ struct drm_dp_mst_port {
* audio-capable.
*/
bool has_audio;
+
+ bool fec_capable;
};
/**
* struct drm_dp_mst_branch - MST branch device.
- * @kref: reference count for this port.
* @rad: Relative Address to talk to this branch device.
* @lct: Link count total to talk to this branch device.
* @num_ports: number of ports on the branch.
* @msg_slots: one bit per transmitted msg slot.
- * @ports: linked list of ports on this branch.
* @port_parent: pointer to the port parent, NULL if toplevel.
* @mgr: topology manager for this branch device.
* @tx_slots: transmission slots for this device.
@@ -121,12 +179,48 @@ struct drm_dp_mst_port {
* to downstream port of parent branches.
*/
struct drm_dp_mst_branch {
- struct kref kref;
+ /**
+ * @topology_kref: refcount for this branch device's lifetime in the
+ * topology, only the DP MST helpers should need to touch this
+ */
+ struct kref topology_kref;
+
+ /**
+ * @malloc_kref: refcount for the memory allocation containing this
+ * structure. See drm_dp_mst_get_mstb_malloc() and
+ * drm_dp_mst_put_mstb_malloc().
+ */
+ struct kref malloc_kref;
+
+#if IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS)
+ /**
+ * @topology_ref_history: A history of each topology
+ * reference/dereference. See CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS.
+ */
+ struct drm_dp_mst_topology_ref_history topology_ref_history;
+#endif
+
+ /**
+ * @destroy_next: linked-list entry used by
+ * drm_dp_delayed_destroy_work()
+ */
+ struct list_head destroy_next;
+
u8 rad[8];
u8 lct;
int num_ports;
int msg_slots;
+ /**
+ * @ports: the list of ports on this branch device. This should be
+ * considered protected for reading by &drm_dp_mst_topology_mgr.lock.
+ * There are two exceptions to this:
+ * &drm_dp_mst_topology_mgr.up_req_work and
+ * &drm_dp_mst_topology_mgr.work, which do not grab
+ * &drm_dp_mst_topology_mgr.lock during reads but are the only
+ * updaters of this list and are protected from updating the list
+ * concurrently by @drm_dp_mst_topology_mgr.probe_lock
+ */
struct list_head ports;
/* list of tx ops queue for this port */
@@ -266,7 +360,7 @@ struct drm_dp_remote_dpcd_write {
struct drm_dp_remote_i2c_read {
u8 num_transactions;
u8 port_number;
- struct {
+ struct drm_dp_remote_i2c_read_tx {
u8 i2c_dev_id;
u8 num_bytes;
u8 *bytes;
@@ -291,6 +385,7 @@ struct drm_dp_port_number_req {
struct drm_dp_enum_path_resources_ack_reply {
u8 port_number;
+ bool fec_capable;
u16 full_payload_bw_number;
u16 avail_payload_bw_number;
};
@@ -384,11 +479,8 @@ struct drm_dp_mst_topology_mgr;
struct drm_dp_mst_topology_cbs {
/* create a connector for a port */
struct drm_connector *(*add_connector)(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, const char *path);
- void (*register_connector)(struct drm_connector *connector);
void (*destroy_connector)(struct drm_dp_mst_topology_mgr *mgr,
struct drm_connector *connector);
- void (*hotplug)(struct drm_dp_mst_topology_mgr *mgr);
-
};
#define DP_MAX_PAYLOAD (sizeof(unsigned long) * 8)
@@ -406,10 +498,17 @@ struct drm_dp_payload {
#define to_dp_mst_topology_state(x) container_of(x, struct drm_dp_mst_topology_state, base)
+struct drm_dp_vcpi_allocation {
+ struct drm_dp_mst_port *port;
+ int vcpi;
+ int pbn;
+ bool dsc_enabled;
+ struct list_head next;
+};
+
struct drm_dp_mst_topology_state {
struct drm_private_state base;
- int avail_slots;
- struct drm_atomic_state *state;
+ struct list_head vcpis;
struct drm_dp_mst_topology_mgr *mgr;
};
@@ -457,28 +556,44 @@ struct drm_dp_mst_topology_mgr {
int conn_base_id;
/**
- * @down_rep_recv: Message receiver state for down replies. This and
- * @up_req_recv are only ever access from the work item, which is
- * serialised.
+ * @down_rep_recv: Message receiver state for down replies.
*/
struct drm_dp_sideband_msg_rx down_rep_recv;
/**
- * @up_req_recv: Message receiver state for up requests. This and
- * @down_rep_recv are only ever access from the work item, which is
- * serialised.
+ * @up_req_recv: Message receiver state for up requests.
*/
struct drm_dp_sideband_msg_rx up_req_recv;
/**
- * @lock: protects mst state, primary, dpcd.
+ * @lock: protects @mst_state, @mst_primary, @dpcd, and
+ * @payload_id_table_cleared.
*/
struct rwlock lock;
/**
+ * @probe_lock: Prevents @work and @up_req_work, the only writers of
+ * &drm_dp_mst_port.mstb and &drm_dp_mst_branch.ports, from racing
+ * while they update the topology.
+ */
+ struct rwlock probe_lock;
+
+ /**
* @mst_state: If this manager is enabled for an MST capable port. False
* if no MST sink/branch devices is connected.
*/
- bool mst_state;
+ bool mst_state : 1;
+
+ /**
+ * @payload_id_table_cleared: Whether or not we've cleared the payload
+ * ID table for @mst_primary. Protected by @lock.
+ */
+ bool payload_id_table_cleared : 1;
+
+ /**
+ * @is_waiting_for_dwn_reply: whether we're waiting for a down reply.
+ */
+ bool is_waiting_for_dwn_reply : 1;
+
/**
* @mst_primary: Pointer to the primary/first branch device.
*/
@@ -498,11 +613,6 @@ struct drm_dp_mst_topology_mgr {
int pbn_div;
/**
- * @state: State information for topology manager
- */
- struct drm_dp_mst_topology_state *state;
-
- /**
* @funcs: Atomic helper callbacks
*/
const struct drm_private_state_funcs *funcs;
@@ -512,6 +622,7 @@ struct drm_dp_mst_topology_mgr {
* &drm_dp_sideband_msg_tx.state once they are queued
*/
struct rwlock qlock;
+
/**
* @tx_msg_downq: List of pending down replies.
*/
@@ -523,11 +634,13 @@ struct drm_dp_mst_topology_mgr {
struct rwlock payload_lock;
/**
* @proposed_vcpis: Array of pointers for the new VCPI allocation. The
- * VCPI structure itself is &drm_dp_mst_port.vcpi.
+ * VCPI structure itself is &drm_dp_mst_port.vcpi, and the size of
+ * this array is determined by @max_payloads.
*/
struct drm_dp_vcpi **proposed_vcpis;
/**
- * @payloads: Array of payloads.
+ * @payloads: Array of payloads. The size of this array is determined
+ * by @max_payloads.
*/
struct drm_dp_payload *payloads;
/**
@@ -556,18 +669,49 @@ struct drm_dp_mst_topology_mgr {
struct work_struct tx_work;
/**
- * @destroy_connector_list: List of to be destroyed connectors.
+ * @destroy_port_list: List of to be destroyed connectors.
+ */
+ struct list_head destroy_port_list;
+ /**
+ * @destroy_branch_device_list: List of to be destroyed branch
+ * devices.
+ */
+ struct list_head destroy_branch_device_list;
+ /**
+ * @delayed_destroy_lock: Protects @destroy_port_list and
+ * @destroy_branch_device_list.
+ */
+ struct rwlock delayed_destroy_lock;
+ /**
+ * @delayed_destroy_work: Work item to destroy MST port and branch
+ * devices, needed to avoid locking inversion.
+ */
+ struct work_struct delayed_destroy_work;
+
+ /**
+ * @up_req_list: List of pending up requests from the topology that
+ * need to be processed, in chronological order.
*/
- struct list_head destroy_connector_list;
+ struct list_head up_req_list;
/**
- * @destroy_connector_lock: Protects @connector_list.
+ * @up_req_lock: Protects @up_req_list
*/
- struct rwlock destroy_connector_lock;
+ struct rwlock up_req_lock;
/**
- * @destroy_connector_work: Work item to destroy connectors. Needed to
- * avoid locking inversion.
+ * @up_req_work: Work item to process up requests received from the
+ * topology. Needed to avoid blocking hotplug handling and sideband
+ * transmissions.
*/
- struct work_struct destroy_connector_work;
+ struct work_struct up_req_work;
+
+#if IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS)
+ /**
+ * @topology_ref_history_lock: protects
+ * &drm_dp_mst_port.topology_ref_history and
+ * &drm_dp_mst_branch.topology_ref_history.
+ */
+ struct rwlock topology_ref_history_lock;
+#endif
};
int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr,
@@ -584,15 +728,18 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
int drm_dp_mst_hpd_irq(struct drm_dp_mst_topology_mgr *mgr, u8 *esi, bool *handled);
-enum drm_connector_status drm_dp_mst_detect_port(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
+int
+drm_dp_mst_detect_port(struct drm_connector *connector,
+ struct drm_modeset_acquire_ctx *ctx,
+ struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_port *port);
bool drm_dp_mst_port_has_audio(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_port *port);
struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
-int drm_dp_calc_pbn_mode(int clock, int bpp);
-
+int drm_dp_calc_pbn_mode(int clock, int bpp, bool dsc);
bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_port *port, int pbn, int slots);
@@ -622,16 +769,141 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
struct drm_dp_mst_topology_mgr *mgr);
void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr);
-int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr);
+int __must_check
+drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr,
+ bool sync);
+
+ssize_t drm_dp_mst_dpcd_read(struct drm_dp_aux *aux,
+ unsigned int offset, void *buffer, size_t size);
+ssize_t drm_dp_mst_dpcd_write(struct drm_dp_aux *aux,
+ unsigned int offset, void *buffer, size_t size);
+
+int drm_dp_mst_connector_late_register(struct drm_connector *connector,
+ struct drm_dp_mst_port *port);
+void drm_dp_mst_connector_early_unregister(struct drm_connector *connector,
+ struct drm_dp_mst_port *port);
+
struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_atomic_state *state,
struct drm_dp_mst_topology_mgr *mgr);
-int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,
- struct drm_dp_mst_topology_mgr *mgr,
- struct drm_dp_mst_port *port, int pbn);
-int drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state,
- struct drm_dp_mst_topology_mgr *mgr,
- int slots);
+int __must_check
+drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,
+ struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_port *port, int pbn,
+ int pbn_div);
+int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state,
+ struct drm_dp_mst_port *port,
+ int pbn, int pbn_div,
+ bool enable);
+int __must_check
+drm_dp_mst_add_affected_dsc_crtcs(struct drm_atomic_state *state,
+ struct drm_dp_mst_topology_mgr *mgr);
+int __must_check
+drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state,
+ struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_port *port);
int drm_dp_send_power_updown_phy(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_port *port, bool power_up);
+int __must_check drm_dp_mst_atomic_check(struct drm_atomic_state *state);
+
+void drm_dp_mst_get_port_malloc(struct drm_dp_mst_port *port);
+void drm_dp_mst_put_port_malloc(struct drm_dp_mst_port *port);
+
+struct drm_dp_aux *drm_dp_mst_dsc_aux_for_port(struct drm_dp_mst_port *port);
+
+extern const struct drm_private_state_funcs drm_dp_mst_topology_state_funcs;
+
+/**
+ * __drm_dp_mst_state_iter_get - private atomic state iterator function for
+ * macro-internal use
+ * @state: &struct drm_atomic_state pointer
+ * @mgr: pointer to the &struct drm_dp_mst_topology_mgr iteration cursor
+ * @old_state: optional pointer to the old &struct drm_dp_mst_topology_state
+ * iteration cursor
+ * @new_state: optional pointer to the new &struct drm_dp_mst_topology_state
+ * iteration cursor
+ * @i: int iteration cursor, for macro-internal use
+ *
+ * Used by for_each_oldnew_mst_mgr_in_state(),
+ * for_each_old_mst_mgr_in_state(), and for_each_new_mst_mgr_in_state(). Don't
+ * call this directly.
+ *
+ * Returns:
+ * True if the current &struct drm_private_obj is a &struct
+ * drm_dp_mst_topology_mgr, false otherwise.
+ */
+static inline bool
+__drm_dp_mst_state_iter_get(struct drm_atomic_state *state,
+ struct drm_dp_mst_topology_mgr **mgr,
+ struct drm_dp_mst_topology_state **old_state,
+ struct drm_dp_mst_topology_state **new_state,
+ int i)
+{
+ struct __drm_private_objs_state *objs_state = &state->private_objs[i];
+
+ if (objs_state->ptr->funcs != &drm_dp_mst_topology_state_funcs)
+ return false;
+
+ *mgr = to_dp_mst_topology_mgr(objs_state->ptr);
+ if (old_state)
+ *old_state = to_dp_mst_topology_state(objs_state->old_state);
+ if (new_state)
+ *new_state = to_dp_mst_topology_state(objs_state->new_state);
+
+ return true;
+}
+
+/**
+ * for_each_oldnew_mst_mgr_in_state - iterate over all DP MST topology
+ * managers in an atomic update
+ * @__state: &struct drm_atomic_state pointer
+ * @mgr: &struct drm_dp_mst_topology_mgr iteration cursor
+ * @old_state: &struct drm_dp_mst_topology_state iteration cursor for the old
+ * state
+ * @new_state: &struct drm_dp_mst_topology_state iteration cursor for the new
+ * state
+ * @__i: int iteration cursor, for macro-internal use
+ *
+ * This iterates over all DRM DP MST topology managers in an atomic update,
+ * tracking both old and new state. This is useful in places where the state
+ * delta needs to be considered, for example in atomic check functions.
+ */
+#define for_each_oldnew_mst_mgr_in_state(__state, mgr, old_state, new_state, __i) \
+ for ((__i) = 0; (__i) < (__state)->num_private_objs; (__i)++) \
+ for_each_if(__drm_dp_mst_state_iter_get((__state), &(mgr), &(old_state), &(new_state), (__i)))
+
+/**
+ * for_each_old_mst_mgr_in_state - iterate over all DP MST topology managers
+ * in an atomic update
+ * @__state: &struct drm_atomic_state pointer
+ * @mgr: &struct drm_dp_mst_topology_mgr iteration cursor
+ * @old_state: &struct drm_dp_mst_topology_state iteration cursor for the old
+ * state
+ * @__i: int iteration cursor, for macro-internal use
+ *
+ * This iterates over all DRM DP MST topology managers in an atomic update,
+ * tracking only the old state. This is useful in disable functions, where we
+ * need the old state the hardware is still in.
+ */
+#define for_each_old_mst_mgr_in_state(__state, mgr, old_state, __i) \
+ for ((__i) = 0; (__i) < (__state)->num_private_objs; (__i)++) \
+ for_each_if(__drm_dp_mst_state_iter_get((__state), &(mgr), &(old_state), NULL, (__i)))
+
+/**
+ * for_each_new_mst_mgr_in_state - iterate over all DP MST topology managers
+ * in an atomic update
+ * @__state: &struct drm_atomic_state pointer
+ * @mgr: &struct drm_dp_mst_topology_mgr iteration cursor
+ * @new_state: &struct drm_dp_mst_topology_state iteration cursor for the new
+ * state
+ * @__i: int iteration cursor, for macro-internal use
+ *
+ * This iterates over all DRM DP MST topology managers in an atomic update,
+ * tracking only the new state. This is useful in enable functions, where we
+ * need the new state the hardware should be in when the atomic commit
+ * operation has completed.
+ */
+#define for_each_new_mst_mgr_in_state(__state, mgr, new_state, __i) \
+ for ((__i) = 0; (__i) < (__state)->num_private_objs; (__i)++) \
+ for_each_if(__drm_dp_mst_state_iter_get((__state), &(mgr), NULL, &(new_state), (__i)))
#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_drv.h b/sys/dev/pci/drm/include/drm/drm_drv.h
index 3d643545b17..7ed43504f2b 100644
--- a/sys/dev/pci/drm/include/drm/drm_drv.h
+++ b/sys/dev/pci/drm/include/drm/drm_drv.h
@@ -1,7 +1,8 @@
-/*-
+/*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All rights reserved.
+ * Copyright (c) 2009-2010, Code Aurora Forum.
+ * Copyright 2016 Intel Corp.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -21,11 +22,6 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- *
*/
#ifndef _DRM_DRV_H_
@@ -36,227 +32,667 @@
#include <drm/drm_device.h>
+#include <uvm/uvm_extern.h>
+
struct drm_file;
struct drm_gem_object;
+struct drm_master;
+struct drm_minor;
+struct dma_buf_attachment;
struct drm_display_mode;
struct drm_mode_create_dumb;
struct drm_printer;
-/* driver capabilities and requirements mask */
-#define DRIVER_USE_AGP 0x1
-#define DRIVER_LEGACY 0x2
-#define DRIVER_PCI_DMA 0x8
-#define DRIVER_SG 0x10
-#define DRIVER_HAVE_DMA 0x20
-#define DRIVER_HAVE_IRQ 0x40
-#define DRIVER_IRQ_SHARED 0x80
-#define DRIVER_GEM 0x1000
-#define DRIVER_MODESET 0x2000
-#define DRIVER_PRIME 0x4000
-#define DRIVER_RENDER 0x8000
-#define DRIVER_ATOMIC 0x10000
-#define DRIVER_KMS_LEGACY_CONTEXT 0x20000
-#define DRIVER_SYNCOBJ 0x40000
-#define DRIVER_PREFER_XBGR_30BPP 0x80000
+/**
+ * enum drm_driver_feature - feature flags
+ *
+ * See &drm_driver.driver_features, drm_device.driver_features and
+ * drm_core_check_feature().
+ */
+enum drm_driver_feature {
+ /**
+ * @DRIVER_GEM:
+ *
+ * Driver use the GEM memory manager. This should be set for all modern
+ * drivers.
+ */
+ DRIVER_GEM = BIT(0),
+ /**
+ * @DRIVER_MODESET:
+ *
+ * Driver supports mode setting interfaces (KMS).
+ */
+ DRIVER_MODESET = BIT(1),
+ /**
+ * @DRIVER_RENDER:
+ *
+ * Driver supports dedicated render nodes. See also the :ref:`section on
+ * render nodes <drm_render_node>` for details.
+ */
+ DRIVER_RENDER = BIT(3),
+ /**
+ * @DRIVER_ATOMIC:
+ *
+ * Driver supports the full atomic modesetting userspace API. Drivers
+ * which only use atomic internally, but do not the support the full
+ * userspace API (e.g. not all properties converted to atomic, or
+ * multi-plane updates are not guaranteed to be tear-free) should not
+ * set this flag.
+ */
+ DRIVER_ATOMIC = BIT(4),
+ /**
+ * @DRIVER_SYNCOBJ:
+ *
+ * Driver supports &drm_syncobj for explicit synchronization of command
+ * submission.
+ */
+ DRIVER_SYNCOBJ = BIT(5),
+ /**
+ * @DRIVER_SYNCOBJ_TIMELINE:
+ *
+ * Driver supports the timeline flavor of &drm_syncobj for explicit
+ * synchronization of command submission.
+ */
+ DRIVER_SYNCOBJ_TIMELINE = BIT(6),
+ /* IMPORTANT: Below are all the legacy flags, add new ones above. */
+
+ /**
+ * @DRIVER_USE_AGP:
+ *
+ * Set up DRM AGP support, see drm_agp_init(), the DRM core will manage
+ * AGP resources. New drivers don't need this.
+ */
+ DRIVER_USE_AGP = BIT(25),
+ /**
+ * @DRIVER_LEGACY:
+ *
+ * Denote a legacy driver using shadow attach. Do not use.
+ */
+ DRIVER_LEGACY = BIT(26),
+ /**
+ * @DRIVER_PCI_DMA:
+ *
+ * Driver is capable of PCI DMA, mapping of PCI DMA buffers to userspace
+ * will be enabled. Only for legacy drivers. Do not use.
+ */
+ DRIVER_PCI_DMA = BIT(27),
+ /**
+ * @DRIVER_SG:
+ *
+ * Driver can perform scatter/gather DMA, allocation and mapping of
+ * scatter/gather buffers will be enabled. Only for legacy drivers. Do
+ * not use.
+ */
+ DRIVER_SG = BIT(28),
+
+ /**
+ * @DRIVER_HAVE_DMA:
+ *
+ * Driver supports DMA, the userspace DMA API will be supported. Only
+ * for legacy drivers. Do not use.
+ */
+ DRIVER_HAVE_DMA = BIT(29),
+ /**
+ * @DRIVER_HAVE_IRQ:
+ *
+ * Legacy irq support. Only for legacy drivers. Do not use.
+ *
+ * New drivers can either use the drm_irq_install() and
+ * drm_irq_uninstall() helper functions, or roll their own irq support
+ * code by calling request_irq() directly.
+ */
+ DRIVER_HAVE_IRQ = BIT(30),
+ /**
+ * @DRIVER_KMS_LEGACY_CONTEXT:
+ *
+ * Used only by nouveau for backwards compatibility with existing
+ * userspace. Do not use.
+ */
+ DRIVER_KMS_LEGACY_CONTEXT = BIT(31),
+};
+
+/**
+ * struct drm_driver - DRM driver structure
+ *
+ * This structure represent the common code for a family of cards. There will be
+ * one &struct drm_device for each card present in this family. It contains lots
+ * of vfunc entries, and a pile of those probably should be moved to more
+ * appropriate places like &drm_mode_config_funcs or into a new operations
+ * structure for GEM drivers.
+ */
struct drm_driver {
- int (*firstopen)(struct drm_device *);
- int (*open)(struct drm_device *, struct drm_file *);
- void (*preclose)(struct drm_device *, struct drm_file *);
- void (*postclose)(struct drm_device *, struct drm_file *);
- void (*lastclose)(struct drm_device *);
- struct uvm_object *(*mmap)(struct drm_device *, voff_t, vsize_t);
- int (*dma_ioctl)(struct drm_device *, struct drm_dma *,
- struct drm_file *);
- int (*irq_handler)(int, void *);
- void (*irq_preinstall) (struct drm_device *);
- int (*irq_install)(struct drm_device *);
- int (*irq_postinstall) (struct drm_device *);
- void (*irq_uninstall)(struct drm_device *);
- int vblank_pipes;
-
- /**
- * get_vblank_counter - get raw hardware vblank counter
- * @dev: DRM device
- * @pipe: counter to fetch
- *
- * Driver callback for fetching a raw hardware vblank counter for @crtc.
- * If a device doesn't have a hardware counter, the driver can simply
- * return the value of drm_vblank_count. The DRM core will account for
- * missed vblank events while interrupts where disabled based on system
- * timestamps.
- *
- * Wraparound handling and loss of events due to modesetting is dealt
- * with in the DRM core code.
- *
- * RETURNS
- * Raw vblank counter value.
- */
- u32 (*get_vblank_counter) (struct drm_device *dev, unsigned int pipe);
+ /**
+ * @load:
+ *
+ * Backward-compatible driver callback to complete
+ * initialization steps after the driver is registered. For
+ * this reason, may suffer from race conditions and its use is
+ * deprecated for new drivers. It is therefore only supported
+ * for existing drivers not yet converted to the new scheme.
+ * See drm_dev_init() and drm_dev_register() for proper and
+ * race-free way to set up a &struct drm_device.
+ *
+ * This is deprecated, do not use!
+ *
+ * Returns:
+ *
+ * Zero on success, non-zero value on failure.
+ */
+ int (*load) (struct drm_device *, unsigned long flags);
/**
- * enable_vblank - enable vblank interrupt events
- * @dev: DRM device
- * @pipe: which irq to enable
+ * @open:
+ *
+ * Driver callback when a new &struct drm_file is opened. Useful for
+ * setting up driver-private data structures like buffer allocators,
+ * execution contexts or similar things. Such driver-private resources
+ * must be released again in @postclose.
+ *
+ * Since the display/modeset side of DRM can only be owned by exactly
+ * one &struct drm_file (see &drm_file.is_master and &drm_device.master)
+ * there should never be a need to set up any modeset related resources
+ * in this callback. Doing so would be a driver design bug.
*
- * Enable vblank interrupts for @crtc. If the device doesn't have
- * a hardware vblank counter, this routine should be a no-op, since
- * interrupts will have to stay on to keep the count accurate.
+ * Returns:
*
- * RETURNS
- * Zero on success, appropriate errno if the given @crtc's vblank
- * interrupt cannot be enabled.
+ * 0 on success, a negative error code on failure, which will be
+ * promoted to userspace as the result of the open() system call.
*/
- int (*enable_vblank) (struct drm_device *dev, unsigned int pipe);
+ int (*open) (struct drm_device *, struct drm_file *);
/**
- * disable_vblank - disable vblank interrupt events
- * @dev: DRM device
- * @pipe: which irq to enable
+ * @postclose:
*
- * Disable vblank interrupts for @crtc. If the device doesn't have
- * a hardware vblank counter, this routine should be a no-op, since
- * interrupts will have to stay on to keep the count accurate.
+ * One of the driver callbacks when a new &struct drm_file is closed.
+ * Useful for tearing down driver-private data structures allocated in
+ * @open like buffer allocators, execution contexts or similar things.
+ *
+ * Since the display/modeset side of DRM can only be owned by exactly
+ * one &struct drm_file (see &drm_file.is_master and &drm_device.master)
+ * there should never be a need to tear down any modeset related
+ * resources in this callback. Doing so would be a driver design bug.
*/
- void (*disable_vblank) (struct drm_device *dev, unsigned int pipe);
+ void (*postclose) (struct drm_device *, struct drm_file *);
/**
- * Called by vblank timestamping code.
+ * @lastclose:
*
- * Return the current display scanout position from a crtc, and an
- * optional accurate ktime_get timestamp of when position was measured.
+ * Called when the last &struct drm_file has been closed and there's
+ * currently no userspace client for the &struct drm_device.
*
- * \param dev DRM device.
- * \param pipe Id of the crtc to query.
- * \param flags Flags from the caller (DRM_CALLED_FROM_VBLIRQ or 0).
- * \param *vpos Target location for current vertical scanout position.
- * \param *hpos Target location for current horizontal scanout position.
- * \param *stime Target location for timestamp taken immediately before
- * scanout position query. Can be NULL to skip timestamp.
- * \param *etime Target location for timestamp taken immediately after
- * scanout position query. Can be NULL to skip timestamp.
- * \param mode Current display timings.
+ * Modern drivers should only use this to force-restore the fbdev
+ * framebuffer using drm_fb_helper_restore_fbdev_mode_unlocked().
+ * Anything else would indicate there's something seriously wrong.
+ * Modern drivers can also use this to execute delayed power switching
+ * state changes, e.g. in conjunction with the :ref:`vga_switcheroo`
+ * infrastructure.
*
- * Returns vpos as a positive number while in active scanout area.
- * Returns vpos as a negative number inside vblank, counting the number
- * of scanlines to go until end of vblank, e.g., -1 means "one scanline
- * until start of active scanout / end of vblank."
+ * This is called after @postclose hook has been called.
*
- * \return Flags, or'ed together as follows:
+ * NOTE:
*
- * DRM_SCANOUTPOS_VALID = Query successful.
- * DRM_SCANOUTPOS_INVBL = Inside vblank.
- * DRM_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of
- * this flag means that returned position may be offset by a constant
- * but unknown small number of scanlines wrt. real scanout position.
+ * All legacy drivers use this callback to de-initialize the hardware.
+ * This is purely because of the shadow-attach model, where the DRM
+ * kernel driver does not really own the hardware. Instead ownershipe is
+ * handled with the help of userspace through an inheritedly racy dance
+ * to set/unset the VT into raw mode.
*
+ * Legacy drivers initialize the hardware in the @firstopen callback,
+ * which isn't even called for modern drivers.
*/
- bool (*get_scanout_position) (struct drm_device *dev, unsigned int pipe,
- bool in_vblank_irq, int *vpos, int *hpos,
- ktime_t *stime, ktime_t *etime,
- const struct drm_display_mode *mode);
+ void (*lastclose) (struct drm_device *);
/**
- * Called by \c drm_get_last_vbltimestamp. Should return a precise
- * timestamp when the most recent VBLANK interval ended or will end.
+ * @unload:
*
- * Specifically, the timestamp in @vblank_time should correspond as
- * closely as possible to the time when the first video scanline of
- * the video frame after the end of VBLANK will start scanning out,
- * the time immediately after end of the VBLANK interval. If the
- * @crtc is currently inside VBLANK, this will be a time in the future.
- * If the @crtc is currently scanning out a frame, this will be the
- * past start time of the current scanout. This is meant to adhere
- * to the OpenML OML_sync_control extension specification.
+ * Reverse the effects of the driver load callback. Ideally,
+ * the clean up performed by the driver should happen in the
+ * reverse order of the initialization. Similarly to the load
+ * hook, this handler is deprecated and its usage should be
+ * dropped in favor of an open-coded teardown function at the
+ * driver layer. See drm_dev_unregister() and drm_dev_put()
+ * for the proper way to remove a &struct drm_device.
*
- * \param dev dev DRM device handle.
- * \param pipe crtc for which timestamp should be returned.
- * \param *max_error Maximum allowable timestamp error in nanoseconds.
- * Implementation should strive to provide timestamp
- * with an error of at most *max_error nanoseconds.
- * Returns true upper bound on error for timestamp.
- * \param *vblank_time Target location for returned vblank timestamp.
- * \param flags 0 = Defaults, no special treatment needed.
- * \param DRM_CALLED_FROM_VBLIRQ = Function is called from vblank
- * irq handler. Some drivers need to apply some workarounds
- * for gpu-specific vblank irq quirks if flag is set.
+ * The unload() hook is called right after unregistering
+ * the device.
*
- * \returns
- * Zero if timestamping isn't supported in current display mode or a
- * negative number on failure. A positive status code on success,
- * which describes how the vblank_time timestamp was computed.
*/
- bool (*get_vblank_timestamp) (struct drm_device *dev, unsigned int pipe,
- int *max_error,
- ktime_t *vblank_time,
- bool in_vblank_irq);
+ void (*unload) (struct drm_device *);
/**
- * Driver-specific constructor for drm_gem_objects, to set up
- * obj->driver_private.
+ * @release:
*
- * Returns 0 on success.
+ * Optional callback for destroying device data after the final
+ * reference is released, i.e. the device is being destroyed. Drivers
+ * using this callback are responsible for calling drm_dev_fini()
+ * to finalize the device and then freeing the struct themselves.
+ */
+ void (*release) (struct drm_device *);
+
+ /**
+ * @irq_handler:
+ *
+ * Interrupt handler called when using drm_irq_install(). Not used by
+ * drivers which implement their own interrupt handling.
+ */
+ irqreturn_t(*irq_handler) (int irq, void *arg);
+
+ /**
+ * @irq_preinstall:
+ *
+ * Optional callback used by drm_irq_install() which is called before
+ * the interrupt handler is registered. This should be used to clear out
+ * any pending interrupts (from e.g. firmware based drives) and reset
+ * the interrupt handling registers.
+ */
+ void (*irq_preinstall) (struct drm_device *dev);
+
+ /**
+ * @irq_postinstall:
+ *
+ * Optional callback used by drm_irq_install() which is called after
+ * the interrupt handler is registered. This should be used to enable
+ * interrupt generation in the hardware.
+ */
+ int (*irq_postinstall) (struct drm_device *dev);
+
+ /**
+ * @irq_uninstall:
+ *
+ * Optional callback used by drm_irq_uninstall() which is called before
+ * the interrupt handler is unregistered. This should be used to disable
+ * interrupt generation in the hardware.
+ */
+ void (*irq_uninstall) (struct drm_device *dev);
+
+ /**
+ * @master_set:
+ *
+ * Called whenever the minor master is set. Only used by vmwgfx.
+ */
+ int (*master_set)(struct drm_device *dev, struct drm_file *file_priv,
+ bool from_open);
+ /**
+ * @master_drop:
+ *
+ * Called whenever the minor master is dropped. Only used by vmwgfx.
+ */
+ void (*master_drop)(struct drm_device *dev, struct drm_file *file_priv);
+
+ /**
+ * @debugfs_init:
+ *
+ * Allows drivers to create driver-specific debugfs files.
+ */
+ int (*debugfs_init)(struct drm_minor *minor);
+
+ /**
+ * @gem_free_object: deconstructor for drm_gem_objects
+ *
+ * This is deprecated and should not be used by new drivers. Use
+ * &drm_gem_object_funcs.free instead.
*/
void (*gem_free_object) (struct drm_gem_object *obj);
+
+ /**
+ * @gem_free_object_unlocked: deconstructor for drm_gem_objects
+ *
+ * This is deprecated and should not be used by new drivers. Use
+ * &drm_gem_object_funcs.free instead.
+ * Compared to @gem_free_object this is not encumbered with
+ * &drm_device.struct_mutex legacy locking schemes.
+ */
void (*gem_free_object_unlocked) (struct drm_gem_object *obj);
+
+ /**
+ * @gem_open_object:
+ *
+ * This callback is deprecated in favour of &drm_gem_object_funcs.open.
+ *
+ * Driver hook called upon gem handle creation
+ */
int (*gem_open_object) (struct drm_gem_object *, struct drm_file *);
+
+ /**
+ * @gem_close_object:
+ *
+ * This callback is deprecated in favour of &drm_gem_object_funcs.close.
+ *
+ * Driver hook called upon gem handle release
+ */
void (*gem_close_object) (struct drm_gem_object *, struct drm_file *);
- void (*gem_print_info)(struct drm_printer *, unsigned int,
- const struct drm_gem_object *);
- int (*gem_fault)(struct drm_gem_object *, struct uvm_faultinfo *,
- off_t, vaddr_t, vm_page_t *, int, int, vm_prot_t, int);
+ /**
+ * @gem_print_info:
+ *
+ * This callback is deprecated in favour of
+ * &drm_gem_object_funcs.print_info.
+ *
+ * If driver subclasses struct &drm_gem_object, it can implement this
+ * optional hook for printing additional driver specific info.
+ *
+ * drm_printf_indent() should be used in the callback passing it the
+ * indent argument.
+ *
+ * This callback is called from drm_gem_print_info().
+ */
+ void (*gem_print_info)(struct drm_printer *p, unsigned int indent,
+ const struct drm_gem_object *obj);
- /* prime: */
- /* export handle -> fd (see drm_gem_prime_handle_to_fd() helper) */
+ /**
+ * @gem_create_object: constructor for gem objects
+ *
+ * Hook for allocating the GEM object struct, for use by the CMA and
+ * SHMEM GEM helpers.
+ */
+ struct drm_gem_object *(*gem_create_object)(struct drm_device *dev,
+ size_t size);
+ /**
+ * @prime_handle_to_fd:
+ *
+ * Main PRIME export function. Should be implemented with
+ * drm_gem_prime_handle_to_fd() for GEM based drivers.
+ *
+ * For an in-depth discussion see :ref:`PRIME buffer sharing
+ * documentation <prime_buffer_sharing>`.
+ */
int (*prime_handle_to_fd)(struct drm_device *dev, struct drm_file *file_priv,
uint32_t handle, uint32_t flags, int *prime_fd);
- /* import fd -> handle (see drm_gem_prime_fd_to_handle() helper) */
+ /**
+ * @prime_fd_to_handle:
+ *
+ * Main PRIME import function. Should be implemented with
+ * drm_gem_prime_fd_to_handle() for GEM based drivers.
+ *
+ * For an in-depth discussion see :ref:`PRIME buffer sharing
+ * documentation <prime_buffer_sharing>`.
+ */
int (*prime_fd_to_handle)(struct drm_device *dev, struct drm_file *file_priv,
int prime_fd, uint32_t *handle);
- /* export GEM -> dmabuf */
- struct dma_buf * (*gem_prime_export)(struct drm_device *dev,
- struct drm_gem_object *obj, int flags);
- /* import dmabuf -> GEM */
+ /**
+ * @gem_prime_export:
+ *
+ * Export hook for GEM drivers. Deprecated in favour of
+ * &drm_gem_object_funcs.export.
+ */
+ struct dma_buf * (*gem_prime_export)(struct drm_gem_object *obj,
+ int flags);
+ /**
+ * @gem_prime_import:
+ *
+ * Import hook for GEM drivers.
+ *
+ * This defaults to drm_gem_prime_import() if not set.
+ */
struct drm_gem_object * (*gem_prime_import)(struct drm_device *dev,
struct dma_buf *dma_buf);
- struct reservation_object * (*gem_prime_res_obj)(
- struct drm_gem_object *obj);
-
- int (*dumb_create)(struct drm_file *file_priv,
- struct drm_device *dev, struct drm_mode_create_dumb *args);
- int (*dumb_map_offset)(struct drm_file *file_priv,
- struct drm_device *dev, uint32_t handle, uint64_t *offset);
- int (*dumb_destroy)(struct drm_file *file_priv,
- struct drm_device *dev, uint32_t handle);
-
- size_t gem_size;
- size_t buf_priv_size;
- size_t file_priv_size;
-
- int major;
- int minor;
- int patchlevel;
- const char *name; /* Simple driver name */
- const char *desc; /* Longer driver name */
- const char *date; /* Date of last major changes. */
+ /**
+ * @gem_prime_pin:
+ *
+ * Deprecated hook in favour of &drm_gem_object_funcs.pin.
+ */
+ int (*gem_prime_pin)(struct drm_gem_object *obj);
+
+ /**
+ * @gem_prime_unpin:
+ *
+ * Deprecated hook in favour of &drm_gem_object_funcs.unpin.
+ */
+ void (*gem_prime_unpin)(struct drm_gem_object *obj);
+
+
+ /**
+ * @gem_prime_get_sg_table:
+ *
+ * Deprecated hook in favour of &drm_gem_object_funcs.get_sg_table.
+ */
+ struct sg_table *(*gem_prime_get_sg_table)(struct drm_gem_object *obj);
+
+ /**
+ * @gem_prime_import_sg_table:
+ *
+ * Optional hook used by the PRIME helper functions
+ * drm_gem_prime_import() respectively drm_gem_prime_import_dev().
+ */
+ struct drm_gem_object *(*gem_prime_import_sg_table)(
+ struct drm_device *dev,
+ struct dma_buf_attachment *attach,
+ struct sg_table *sgt);
+ /**
+ * @gem_prime_vmap:
+ *
+ * Deprecated vmap hook for GEM drivers. Please use
+ * &drm_gem_object_funcs.vmap instead.
+ */
+ void *(*gem_prime_vmap)(struct drm_gem_object *obj);
+
+ /**
+ * @gem_prime_vunmap:
+ *
+ * Deprecated vunmap hook for GEM drivers. Please use
+ * &drm_gem_object_funcs.vunmap instead.
+ */
+ void (*gem_prime_vunmap)(struct drm_gem_object *obj, void *vaddr);
+
+ /**
+ * @gem_prime_mmap:
+ *
+ * mmap hook for GEM drivers, used to implement dma-buf mmap in the
+ * PRIME helpers.
+ *
+ * FIXME: There's way too much duplication going on here, and also moved
+ * to &drm_gem_object_funcs.
+ */
+#ifdef __linux__
+ int (*gem_prime_mmap)(struct drm_gem_object *obj,
+ struct vm_area_struct *vma);
+#endif
+
+#ifdef __OpenBSD__
+ struct uvm_object *(*mmap)(struct file *, vm_prot_t, voff_t, vsize_t);
+ size_t gem_size;
+ size_t buf_priv_size;
+ size_t file_priv_size;
+#endif
+
+ /**
+ * @dumb_create:
+ *
+ * This creates a new dumb buffer in the driver's backing storage manager (GEM,
+ * TTM or something else entirely) and returns the resulting buffer handle. This
+ * handle can then be wrapped up into a framebuffer modeset object.
+ *
+ * Note that userspace is not allowed to use such objects for render
+ * acceleration - drivers must create their own private ioctls for such a use
+ * case.
+ *
+ * Width, height and depth are specified in the &drm_mode_create_dumb
+ * argument. The callback needs to fill the handle, pitch and size for
+ * the created buffer.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ *
+ * Zero on success, negative errno on failure.
+ */
+ int (*dumb_create)(struct drm_file *file_priv,
+ struct drm_device *dev,
+ struct drm_mode_create_dumb *args);
+ /**
+ * @dumb_map_offset:
+ *
+ * Allocate an offset in the drm device node's address space to be able to
+ * memory map a dumb buffer.
+ *
+ * The default implementation is drm_gem_create_mmap_offset(). GEM based
+ * drivers must not overwrite this.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ *
+ * Zero on success, negative errno on failure.
+ */
+ int (*dumb_map_offset)(struct drm_file *file_priv,
+ struct drm_device *dev, uint32_t handle,
+ uint64_t *offset);
+ /**
+ * @dumb_destroy:
+ *
+ * This destroys the userspace handle for the given dumb backing storage buffer.
+ * Since buffer objects must be reference counted in the kernel a buffer object
+ * won't be immediately freed if a framebuffer modeset object still uses it.
+ *
+ * Called by the user via ioctl.
+ *
+ * The default implementation is drm_gem_dumb_destroy(). GEM based drivers
+ * must not overwrite this.
+ *
+ * Returns:
+ *
+ * Zero on success, negative errno on failure.
+ */
+ int (*dumb_destroy)(struct drm_file *file_priv,
+ struct drm_device *dev,
+ uint32_t handle);
+
+ /**
+ * @gem_vm_ops: Driver private ops for this object
+ *
+ * For GEM drivers this is deprecated in favour of
+ * &drm_gem_object_funcs.vm_ops.
+ */
+ const struct vm_operations_struct *gem_vm_ops;
+
+#ifdef __OpenBSD__
+ int (*gem_fault)(struct drm_gem_object *,
+ struct uvm_faultinfo *, off_t, vaddr_t,
+ vm_page_t *, int, int, vm_prot_t, int);
+#endif
+
+ /** @major: driver major number */
+ int major;
+ /** @minor: driver minor number */
+ int minor;
+ /** @patchlevel: driver patch level */
+ int patchlevel;
+ /** @name: driver name */
+ char *name;
+ /** @desc: driver description */
+ char *desc;
+ /** @date: driver date */
+ char *date;
+
+ /**
+ * @driver_features:
+ * Driver features, see &enum drm_driver_feature. Drivers can disable
+ * some features on a per-instance basis using
+ * &drm_device.driver_features.
+ */
u32 driver_features;
+
+ /**
+ * @ioctls:
+ *
+ * Array of driver-private IOCTL description entries. See the chapter on
+ * :ref:`IOCTL support in the userland interfaces
+ * chapter<drm_driver_ioctl>` for the full details.
+ */
+
const struct drm_ioctl_desc *ioctls;
+ /** @num_ioctls: Number of entries in @ioctls. */
int num_ioctls;
+ /**
+ * @fops:
+ *
+ * File operations for the DRM device node. See the discussion in
+ * :ref:`file operations<drm_driver_fops>` for in-depth coverage and
+ * some examples.
+ */
+ const struct file_operations *fops;
+
+ /* Everything below here is for legacy driver, never use! */
+ /* private: */
+
+ /* List of devices hanging off this driver with stealth attach. */
+ struct list_head legacy_dev_list;
+ int (*firstopen) (struct drm_device *);
+ void (*preclose) (struct drm_device *, struct drm_file *file_priv);
+ int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv);
+ int (*dma_quiescent) (struct drm_device *);
+ int (*context_dtor) (struct drm_device *dev, int context);
+ u32 (*get_vblank_counter)(struct drm_device *dev, unsigned int pipe);
+ int (*enable_vblank)(struct drm_device *dev, unsigned int pipe);
+ void (*disable_vblank)(struct drm_device *dev, unsigned int pipe);
+ int dev_priv_size;
};
-extern unsigned int drm_debug;
+int drm_dev_init(struct drm_device *dev,
+ struct drm_driver *driver,
+ struct device *parent);
+int devm_drm_dev_init(struct device *parent,
+ struct drm_device *dev,
+ struct drm_driver *driver);
+void drm_dev_fini(struct drm_device *dev);
+
+struct drm_device *drm_dev_alloc(struct drm_driver *driver,
+ struct device *parent);
+int drm_dev_register(struct drm_device *dev, unsigned long flags);
+void drm_dev_unregister(struct drm_device *dev);
+
+void drm_dev_get(struct drm_device *dev);
+void drm_dev_put(struct drm_device *dev);
+void drm_put_dev(struct drm_device *dev);
+bool drm_dev_enter(struct drm_device *dev, int *idx);
+void drm_dev_exit(int idx);
+void drm_dev_unplug(struct drm_device *dev);
-static inline void
-drm_dev_get(struct drm_device *dev)
+/**
+ * drm_dev_is_unplugged - is a DRM device unplugged
+ * @dev: DRM device
+ *
+ * This function can be called to check whether a hotpluggable is unplugged.
+ * Unplugging itself is singalled through drm_dev_unplug(). If a device is
+ * unplugged, these two functions guarantee that any store before calling
+ * drm_dev_unplug() is visible to callers of this function after it completes
+ *
+ * WARNING: This function fundamentally races against drm_dev_unplug(). It is
+ * recommended that drivers instead use the underlying drm_dev_enter() and
+ * drm_dev_exit() function pairs.
+ */
+static inline bool drm_dev_is_unplugged(struct drm_device *dev)
{
+ int idx;
+
+ if (drm_dev_enter(dev, &idx)) {
+ drm_dev_exit(idx);
+ return false;
+ }
+
+ return true;
}
-static inline void
-drm_dev_put(struct drm_device *dev)
+/**
+ * drm_core_check_all_features - check driver feature flags mask
+ * @dev: DRM device to check
+ * @features: feature flag(s) mask
+ *
+ * This checks @dev for driver features, see &drm_driver.driver_features,
+ * &drm_device.driver_features, and the various &enum drm_driver_feature flags.
+ *
+ * Returns true if all features in the @features mask are supported, false
+ * otherwise.
+ */
+static inline bool drm_core_check_all_features(const struct drm_device *dev,
+ u32 features)
{
+ u32 supported = dev->driver->driver_features & dev->driver_features;
+
+ return features && (supported & features) == features;
}
/**
@@ -264,14 +700,15 @@ drm_dev_put(struct drm_device *dev)
* @dev: DRM device to check
* @feature: feature flag
*
- * This checks @dev for driver features, see &drm_driver.driver_features and the
- * various DRIVER_\* flags.
+ * This checks @dev for driver features, see &drm_driver.driver_features,
+ * &drm_device.driver_features, and the various &enum drm_driver_feature flags.
*
* Returns true if the @feature is supported, false otherwise.
*/
-static inline bool drm_core_check_feature(struct drm_device *dev, int feature)
+static inline bool drm_core_check_feature(const struct drm_device *dev,
+ enum drm_driver_feature feature)
{
- return dev->driver->driver_features & feature;
+ return drm_core_check_all_features(dev, feature);
}
/**
@@ -288,10 +725,25 @@ static inline bool drm_drv_uses_atomic_modeset(struct drm_device *dev)
(dev->mode_config.funcs && dev->mode_config.funcs->atomic_commit != NULL);
}
-int drm_dev_register(struct drm_device *, unsigned long);
-void drm_dev_unregister(struct drm_device *);
-int drm_getpciinfo(struct drm_device *, void *, struct drm_file *);
-const struct drm_pcidev *drm_find_description(int, int,
- const struct drm_pcidev *);
+
+int drm_dev_set_unique(struct drm_device *dev, const char *name);
+
+struct drm_file *drm_find_file_by_minor(struct drm_device *, int);
+struct drm_device *drm_get_device_from_kdev(dev_t);
+
+#ifdef __OpenBSD__
+
+void drm_attach_platform(struct drm_driver *, bus_space_tag_t, bus_dma_tag_t,
+ struct device *, struct drm_device *);
+struct drm_device *drm_attach_pci(struct drm_driver *,
+ struct pci_attach_args *, int, int, struct device *, struct drm_device *);
+
+int drm_pciprobe(struct pci_attach_args *, const struct pci_device_id * );
+const struct pci_device_id *drm_find_description(int, int,
+ const struct pci_device_id *);
+
+int drm_getpciinfo(struct drm_device *, void *, struct drm_file *);
+
+#endif
#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_dsc.h b/sys/dev/pci/drm/include/drm/drm_dsc.h
new file mode 100644
index 00000000000..887954cbfc6
--- /dev/null
+++ b/sys/dev/pci/drm/include/drm/drm_dsc.h
@@ -0,0 +1,609 @@
+/* SPDX-License-Identifier: MIT
+ * Copyright (C) 2018 Intel Corp.
+ *
+ * Authors:
+ * Manasi Navare <manasi.d.navare@intel.com>
+ */
+
+#ifndef DRM_DSC_H_
+#define DRM_DSC_H_
+
+#include <drm/drm_dp_helper.h>
+
+/* VESA Display Stream Compression DSC 1.2 constants */
+#define DSC_NUM_BUF_RANGES 15
+#define DSC_MUX_WORD_SIZE_8_10_BPC 48
+#define DSC_MUX_WORD_SIZE_12_BPC 64
+#define DSC_RC_PIXELS_PER_GROUP 3
+#define DSC_SCALE_DECREMENT_INTERVAL_MAX 4095
+#define DSC_RANGE_BPG_OFFSET_MASK 0x3f
+
+/* DSC Rate Control Constants */
+#define DSC_RC_MODEL_SIZE_CONST 8192
+#define DSC_RC_EDGE_FACTOR_CONST 6
+#define DSC_RC_TGT_OFFSET_HI_CONST 3
+#define DSC_RC_TGT_OFFSET_LO_CONST 3
+
+/* DSC PPS constants and macros */
+#define DSC_PPS_VERSION_MAJOR_SHIFT 4
+#define DSC_PPS_BPC_SHIFT 4
+#define DSC_PPS_MSB_SHIFT 8
+#define DSC_PPS_LSB_MASK (0xFF << 0)
+#define DSC_PPS_BPP_HIGH_MASK (0x3 << 8)
+#define DSC_PPS_VBR_EN_SHIFT 2
+#define DSC_PPS_SIMPLE422_SHIFT 3
+#define DSC_PPS_CONVERT_RGB_SHIFT 4
+#define DSC_PPS_BLOCK_PRED_EN_SHIFT 5
+#define DSC_PPS_INIT_XMIT_DELAY_HIGH_MASK (0x3 << 8)
+#define DSC_PPS_SCALE_DEC_INT_HIGH_MASK (0xF << 8)
+#define DSC_PPS_RC_TGT_OFFSET_HI_SHIFT 4
+#define DSC_PPS_RC_RANGE_MINQP_SHIFT 11
+#define DSC_PPS_RC_RANGE_MAXQP_SHIFT 6
+#define DSC_PPS_NATIVE_420_SHIFT 1
+#define DSC_1_2_MAX_LINEBUF_DEPTH_BITS 16
+#define DSC_1_2_MAX_LINEBUF_DEPTH_VAL 0
+#define DSC_1_1_MAX_LINEBUF_DEPTH_BITS 13
+
+/**
+ * struct drm_dsc_rc_range_parameters - DSC Rate Control range parameters
+ *
+ * This defines different rate control parameters used by the DSC engine
+ * to compress the frame.
+ */
+struct drm_dsc_rc_range_parameters {
+ /**
+ * @range_min_qp: Min Quantization Parameters allowed for this range
+ */
+ u8 range_min_qp;
+ /**
+ * @range_max_qp: Max Quantization Parameters allowed for this range
+ */
+ u8 range_max_qp;
+ /**
+ * @range_bpg_offset:
+ * Bits/group offset to apply to target for this group
+ */
+ u8 range_bpg_offset;
+};
+
+/**
+ * struct drm_dsc_config - Parameters required to configure DSC
+ *
+ * Driver populates this structure with all the parameters required
+ * to configure the display stream compression on the source.
+ */
+struct drm_dsc_config {
+ /**
+ * @line_buf_depth:
+ * Bits per component for previous reconstructed line buffer
+ */
+ u8 line_buf_depth;
+ /**
+ * @bits_per_component: Bits per component to code (8/10/12)
+ */
+ u8 bits_per_component;
+ /**
+ * @convert_rgb:
+ * Flag to indicate if RGB - YCoCg conversion is needed
+ * True if RGB input, False if YCoCg input
+ */
+ bool convert_rgb;
+ /**
+ * @slice_count: Number fo slices per line used by the DSC encoder
+ */
+ u8 slice_count;
+ /**
+ * @slice_width: Width of each slice in pixels
+ */
+ u16 slice_width;
+ /**
+ * @slice_height: Slice height in pixels
+ */
+ u16 slice_height;
+ /**
+ * @simple_422: True if simple 4_2_2 mode is enabled else False
+ */
+ bool simple_422;
+ /**
+ * @pic_width: Width of the input display frame in pixels
+ */
+ u16 pic_width;
+ /**
+ * @pic_height: Vertical height of the input display frame
+ */
+ u16 pic_height;
+ /**
+ * @rc_tgt_offset_high:
+ * Offset to bits/group used by RC to determine QP adjustment
+ */
+ u8 rc_tgt_offset_high;
+ /**
+ * @rc_tgt_offset_low:
+ * Offset to bits/group used by RC to determine QP adjustment
+ */
+ u8 rc_tgt_offset_low;
+ /**
+ * @bits_per_pixel:
+ * Target bits per pixel with 4 fractional bits, bits_per_pixel << 4
+ */
+ u16 bits_per_pixel;
+ /**
+ * @rc_edge_factor:
+ * Factor to determine if an edge is present based on the bits produced
+ */
+ u8 rc_edge_factor;
+ /**
+ * @rc_quant_incr_limit1:
+ * Slow down incrementing once the range reaches this value
+ */
+ u8 rc_quant_incr_limit1;
+ /**
+ * @rc_quant_incr_limit0:
+ * Slow down incrementing once the range reaches this value
+ */
+ u8 rc_quant_incr_limit0;
+ /**
+ * @initial_xmit_delay:
+ * Number of pixels to delay the initial transmission
+ */
+ u16 initial_xmit_delay;
+ /**
+ * @initial_dec_delay:
+ * Initial decoder delay, number of pixel times that the decoder
+ * accumulates data in its rate buffer before starting to decode
+ * and output pixels.
+ */
+ u16 initial_dec_delay;
+ /**
+ * @block_pred_enable:
+ * True if block prediction is used to code any groups within the
+ * picture. False if BP not used
+ */
+ bool block_pred_enable;
+ /**
+ * @first_line_bpg_offset:
+ * Number of additional bits allocated for each group on the first
+ * line of slice.
+ */
+ u8 first_line_bpg_offset;
+ /**
+ * @initial_offset: Value to use for RC model offset at slice start
+ */
+ u16 initial_offset;
+ /**
+ * @rc_buf_thresh: Thresholds defining each of the buffer ranges
+ */
+ u16 rc_buf_thresh[DSC_NUM_BUF_RANGES - 1];
+ /**
+ * @rc_range_params:
+ * Parameters for each of the RC ranges defined in
+ * &struct drm_dsc_rc_range_parameters
+ */
+ struct drm_dsc_rc_range_parameters rc_range_params[DSC_NUM_BUF_RANGES];
+ /**
+ * @rc_model_size: Total size of RC model
+ */
+ u16 rc_model_size;
+ /**
+ * @flatness_min_qp: Minimum QP where flatness information is sent
+ */
+ u8 flatness_min_qp;
+ /**
+ * @flatness_max_qp: Maximum QP where flatness information is sent
+ */
+ u8 flatness_max_qp;
+ /**
+ * @initial_scale_value: Initial value for the scale factor
+ */
+ u8 initial_scale_value;
+ /**
+ * @scale_decrement_interval:
+ * Specifies number of group times between decrementing the scale factor
+ * at beginning of a slice.
+ */
+ u16 scale_decrement_interval;
+ /**
+ * @scale_increment_interval:
+ * Number of group times between incrementing the scale factor value
+ * used at the beginning of a slice.
+ */
+ u16 scale_increment_interval;
+ /**
+ * @nfl_bpg_offset: Non first line BPG offset to be used
+ */
+ u16 nfl_bpg_offset;
+ /**
+ * @slice_bpg_offset: BPG offset used to enforce slice bit
+ */
+ u16 slice_bpg_offset;
+ /**
+ * @final_offset: Final RC linear transformation offset value
+ */
+ u16 final_offset;
+ /**
+ * @vbr_enable: True if VBR mode is enabled, false if disabled
+ */
+ bool vbr_enable;
+ /**
+ * @mux_word_size: Mux word size (in bits) for SSM mode
+ */
+ u8 mux_word_size;
+ /**
+ * @slice_chunk_size:
+ * The (max) size in bytes of the "chunks" that are used in slice
+ * multiplexing.
+ */
+ u16 slice_chunk_size;
+ /**
+ * @rc_bits: Rate control buffer size in bits
+ */
+ u16 rc_bits;
+ /**
+ * @dsc_version_minor: DSC minor version
+ */
+ u8 dsc_version_minor;
+ /**
+ * @dsc_version_major: DSC major version
+ */
+ u8 dsc_version_major;
+ /**
+ * @native_422: True if Native 4:2:2 supported, else false
+ */
+ bool native_422;
+ /**
+ * @native_420: True if Native 4:2:0 supported else false.
+ */
+ bool native_420;
+ /**
+ * @second_line_bpg_offset:
+ * Additional bits/grp for seconnd line of slice for native 4:2:0
+ */
+ u8 second_line_bpg_offset;
+ /**
+ * @nsl_bpg_offset:
+ * Num of bits deallocated for each grp that is not in second line of
+ * slice
+ */
+ u16 nsl_bpg_offset;
+ /**
+ * @second_line_offset_adj:
+ * Offset adjustment for second line in Native 4:2:0 mode
+ */
+ u16 second_line_offset_adj;
+};
+
+/**
+ * struct picture_parameter_set - Represents 128 bytes of Picture Parameter Set
+ *
+ * The VESA DSC standard defines picture parameter set (PPS) which display
+ * stream compression encoders must communicate to decoders.
+ * The PPS is encapsulated in 128 bytes (PPS 0 through PPS 127). The fields in
+ * this structure are as per Table 4.1 in Vesa DSC specification v1.1/v1.2.
+ * The PPS fields that span over more than a byte should be stored in Big Endian
+ * format.
+ */
+struct drm_dsc_picture_parameter_set {
+ /**
+ * @dsc_version:
+ * PPS0[3:0] - dsc_version_minor: Contains Minor version of DSC
+ * PPS0[7:4] - dsc_version_major: Contains major version of DSC
+ */
+ u8 dsc_version;
+ /**
+ * @pps_identifier:
+ * PPS1[7:0] - Application specific identifier that can be
+ * used to differentiate between different PPS tables.
+ */
+ u8 pps_identifier;
+ /**
+ * @pps_reserved:
+ * PPS2[7:0]- RESERVED Byte
+ */
+ u8 pps_reserved;
+ /**
+ * @pps_3:
+ * PPS3[3:0] - linebuf_depth: Contains linebuffer bit depth used to
+ * generate the bitstream. (0x0 - 16 bits for DSC 1.2, 0x8 - 8 bits,
+ * 0xA - 10 bits, 0xB - 11 bits, 0xC - 12 bits, 0xD - 13 bits,
+ * 0xE - 14 bits for DSC1.2, 0xF - 14 bits for DSC 1.2.
+ * PPS3[7:4] - bits_per_component: Bits per component for the original
+ * pixels of the encoded picture.
+ * 0x0 = 16bpc (allowed only when dsc_version_minor = 0x2)
+ * 0x8 = 8bpc, 0xA = 10bpc, 0xC = 12bpc, 0xE = 14bpc (also
+ * allowed only when dsc_minor_version = 0x2)
+ */
+ u8 pps_3;
+ /**
+ * @pps_4:
+ * PPS4[1:0] -These are the most significant 2 bits of
+ * compressed BPP bits_per_pixel[9:0] syntax element.
+ * PPS4[2] - vbr_enable: 0 = VBR disabled, 1 = VBR enabled
+ * PPS4[3] - simple_422: Indicates if decoder drops samples to
+ * reconstruct the 4:2:2 picture.
+ * PPS4[4] - Convert_rgb: Indicates if DSC color space conversion is
+ * active.
+ * PPS4[5] - blobk_pred_enable: Indicates if BP is used to code any
+ * groups in picture
+ * PPS4[7:6] - Reseved bits
+ */
+ u8 pps_4;
+ /**
+ * @bits_per_pixel_low:
+ * PPS5[7:0] - This indicates the lower significant 8 bits of
+ * the compressed BPP bits_per_pixel[9:0] element.
+ */
+ u8 bits_per_pixel_low;
+ /**
+ * @pic_height:
+ * PPS6[7:0], PPS7[7:0] -pic_height: Specifies the number of pixel rows
+ * within the raster.
+ */
+ __be16 pic_height;
+ /**
+ * @pic_width:
+ * PPS8[7:0], PPS9[7:0] - pic_width: Number of pixel columns within
+ * the raster.
+ */
+ __be16 pic_width;
+ /**
+ * @slice_height:
+ * PPS10[7:0], PPS11[7:0] - Slice height in units of pixels.
+ */
+ __be16 slice_height;
+ /**
+ * @slice_width:
+ * PPS12[7:0], PPS13[7:0] - Slice width in terms of pixels.
+ */
+ __be16 slice_width;
+ /**
+ * @chunk_size:
+ * PPS14[7:0], PPS15[7:0] - Size in units of bytes of the chunks
+ * that are used for slice multiplexing.
+ */
+ __be16 chunk_size;
+ /**
+ * @initial_xmit_delay_high:
+ * PPS16[1:0] - Most Significant two bits of initial transmission delay.
+ * It specifies the number of pixel times that the encoder waits before
+ * transmitting data from its rate buffer.
+ * PPS16[7:2] - Reserved
+ */
+ u8 initial_xmit_delay_high;
+ /**
+ * @initial_xmit_delay_low:
+ * PPS17[7:0] - Least significant 8 bits of initial transmission delay.
+ */
+ u8 initial_xmit_delay_low;
+ /**
+ * @initial_dec_delay:
+ *
+ * PPS18[7:0], PPS19[7:0] - Initial decoding delay which is the number
+ * of pixel times that the decoder accumulates data in its rate buffer
+ * before starting to decode and output pixels.
+ */
+ __be16 initial_dec_delay;
+ /**
+ * @pps20_reserved:
+ *
+ * PPS20[7:0] - Reserved
+ */
+ u8 pps20_reserved;
+ /**
+ * @initial_scale_value:
+ * PPS21[5:0] - Initial rcXformScale factor used at beginning
+ * of a slice.
+ * PPS21[7:6] - Reserved
+ */
+ u8 initial_scale_value;
+ /**
+ * @scale_increment_interval:
+ * PPS22[7:0], PPS23[7:0] - Number of group times between incrementing
+ * the rcXformScale factor at end of a slice.
+ */
+ __be16 scale_increment_interval;
+ /**
+ * @scale_decrement_interval_high:
+ * PPS24[3:0] - Higher 4 bits indicating number of group times between
+ * decrementing the rcXformScale factor at beginning of a slice.
+ * PPS24[7:4] - Reserved
+ */
+ u8 scale_decrement_interval_high;
+ /**
+ * @scale_decrement_interval_low:
+ * PPS25[7:0] - Lower 8 bits of scale decrement interval
+ */
+ u8 scale_decrement_interval_low;
+ /**
+ * @pps26_reserved:
+ * PPS26[7:0]
+ */
+ u8 pps26_reserved;
+ /**
+ * @first_line_bpg_offset:
+ * PPS27[4:0] - Number of additional bits that are allocated
+ * for each group on first line of a slice.
+ * PPS27[7:5] - Reserved
+ */
+ u8 first_line_bpg_offset;
+ /**
+ * @nfl_bpg_offset:
+ * PPS28[7:0], PPS29[7:0] - Number of bits including frac bits
+ * deallocated for each group for groups after the first line of slice.
+ */
+ __be16 nfl_bpg_offset;
+ /**
+ * @slice_bpg_offset:
+ * PPS30, PPS31[7:0] - Number of bits that are deallocated for each
+ * group to enforce the slice constraint.
+ */
+ __be16 slice_bpg_offset;
+ /**
+ * @initial_offset:
+ * PPS32,33[7:0] - Initial value for rcXformOffset
+ */
+ __be16 initial_offset;
+ /**
+ * @final_offset:
+ * PPS34,35[7:0] - Maximum end-of-slice value for rcXformOffset
+ */
+ __be16 final_offset;
+ /**
+ * @flatness_min_qp:
+ * PPS36[4:0] - Minimum QP at which flatness is signaled and
+ * flatness QP adjustment is made.
+ * PPS36[7:5] - Reserved
+ */
+ u8 flatness_min_qp;
+ /**
+ * @flatness_max_qp:
+ * PPS37[4:0] - Max QP at which flatness is signalled and
+ * the flatness adjustment is made.
+ * PPS37[7:5] - Reserved
+ */
+ u8 flatness_max_qp;
+ /**
+ * @rc_model_size:
+ * PPS38,39[7:0] - Number of bits within RC Model.
+ */
+ __be16 rc_model_size;
+ /**
+ * @rc_edge_factor:
+ * PPS40[3:0] - Ratio of current activity vs, previous
+ * activity to determine presence of edge.
+ * PPS40[7:4] - Reserved
+ */
+ u8 rc_edge_factor;
+ /**
+ * @rc_quant_incr_limit0:
+ * PPS41[4:0] - QP threshold used in short term RC
+ * PPS41[7:5] - Reserved
+ */
+ u8 rc_quant_incr_limit0;
+ /**
+ * @rc_quant_incr_limit1:
+ * PPS42[4:0] - QP threshold used in short term RC
+ * PPS42[7:5] - Reserved
+ */
+ u8 rc_quant_incr_limit1;
+ /**
+ * @rc_tgt_offset:
+ * PPS43[3:0] - Lower end of the variability range around the target
+ * bits per group that is allowed by short term RC.
+ * PPS43[7:4]- Upper end of the variability range around the target
+ * bits per group that i allowed by short term rc.
+ */
+ u8 rc_tgt_offset;
+ /**
+ * @rc_buf_thresh:
+ * PPS44[7:0] - PPS57[7:0] - Specifies the thresholds in RC model for
+ * the 15 ranges defined by 14 thresholds.
+ */
+ u8 rc_buf_thresh[DSC_NUM_BUF_RANGES - 1];
+ /**
+ * @rc_range_parameters:
+ * PPS58[7:0] - PPS87[7:0]
+ * Parameters that correspond to each of the 15 ranges.
+ */
+ __be16 rc_range_parameters[DSC_NUM_BUF_RANGES];
+ /**
+ * @native_422_420:
+ * PPS88[0] - 0 = Native 4:2:2 not used
+ * 1 = Native 4:2:2 used
+ * PPS88[1] - 0 = Native 4:2:0 not use
+ * 1 = Native 4:2:0 used
+ * PPS88[7:2] - Reserved 6 bits
+ */
+ u8 native_422_420;
+ /**
+ * @second_line_bpg_offset:
+ * PPS89[4:0] - Additional bits/group budget for the
+ * second line of a slice in Native 4:2:0 mode.
+ * Set to 0 if DSC minor version is 1 or native420 is 0.
+ * PPS89[7:5] - Reserved
+ */
+ u8 second_line_bpg_offset;
+ /**
+ * @nsl_bpg_offset:
+ * PPS90[7:0], PPS91[7:0] - Number of bits that are deallocated
+ * for each group that is not in the second line of a slice.
+ */
+ __be16 nsl_bpg_offset;
+ /**
+ * @second_line_offset_adj:
+ * PPS92[7:0], PPS93[7:0] - Used as offset adjustment for the second
+ * line in Native 4:2:0 mode.
+ */
+ __be16 second_line_offset_adj;
+ /**
+ * @pps_long_94_reserved:
+ * PPS 94, 95, 96, 97 - Reserved
+ */
+ u32 pps_long_94_reserved;
+ /**
+ * @pps_long_98_reserved:
+ * PPS 98, 99, 100, 101 - Reserved
+ */
+ u32 pps_long_98_reserved;
+ /**
+ * @pps_long_102_reserved:
+ * PPS 102, 103, 104, 105 - Reserved
+ */
+ u32 pps_long_102_reserved;
+ /**
+ * @pps_long_106_reserved:
+ * PPS 106, 107, 108, 109 - reserved
+ */
+ u32 pps_long_106_reserved;
+ /**
+ * @pps_long_110_reserved:
+ * PPS 110, 111, 112, 113 - reserved
+ */
+ u32 pps_long_110_reserved;
+ /**
+ * @pps_long_114_reserved:
+ * PPS 114 - 117 - reserved
+ */
+ u32 pps_long_114_reserved;
+ /**
+ * @pps_long_118_reserved:
+ * PPS 118 - 121 - reserved
+ */
+ u32 pps_long_118_reserved;
+ /**
+ * @pps_long_122_reserved:
+ * PPS 122- 125 - reserved
+ */
+ u32 pps_long_122_reserved;
+ /**
+ * @pps_short_126_reserved:
+ * PPS 126, 127 - reserved
+ */
+ __be16 pps_short_126_reserved;
+} __packed;
+
+/**
+ * struct drm_dsc_pps_infoframe - DSC infoframe carrying the Picture Parameter
+ * Set Metadata
+ *
+ * This structure represents the DSC PPS infoframe required to send the Picture
+ * Parameter Set metadata required before enabling VESA Display Stream
+ * Compression. This is based on the DP Secondary Data Packet structure and
+ * comprises of SDP Header as defined &struct struct dp_sdp_header in drm_dp_helper.h
+ * and PPS payload defined in &struct drm_dsc_picture_parameter_set.
+ *
+ * @pps_header: Header for PPS as per DP SDP header format of type
+ * &struct dp_sdp_header
+ * @pps_payload: PPS payload fields as per DSC specification Table 4-1
+ * as represented in &struct drm_dsc_picture_parameter_set
+ */
+struct drm_dsc_pps_infoframe {
+ struct dp_sdp_header pps_header;
+ struct drm_dsc_picture_parameter_set pps_payload;
+} __packed;
+
+void drm_dsc_dp_pps_header_init(struct dp_sdp_header *pps_header);
+void drm_dsc_pps_payload_pack(struct drm_dsc_picture_parameter_set *pps_sdp,
+ const struct drm_dsc_config *dsc_cfg);
+int drm_dsc_compute_rc_parameters(struct drm_dsc_config *vdsc_cfg);
+
+#endif /* _DRM_DSC_H_ */
diff --git a/sys/dev/pci/drm/include/drm/drm_edid.h b/sys/dev/pci/drm/include/drm/drm_edid.h
index 269249b7f09..34b15e3d070 100644
--- a/sys/dev/pci/drm/include/drm/drm_edid.h
+++ b/sys/dev/pci/drm/include/drm/drm_edid.h
@@ -25,6 +25,10 @@
#include <linux/types.h>
#include <linux/hdmi.h>
+#include <drm/drm_mode.h>
+
+struct drm_device;
+struct i2c_adapter;
#define EDID_LENGTH 128
#define DDC_ADDR 0x50
@@ -87,6 +91,11 @@ struct detailed_data_string {
u8 str[13];
} __attribute__((packed));
+#define DRM_EDID_DEFAULT_GTF_SUPPORT_FLAG 0x00
+#define DRM_EDID_RANGE_LIMITS_ONLY_FLAG 0x01
+#define DRM_EDID_SECONDARY_GTF_SUPPORT_FLAG 0x02
+#define DRM_EDID_CVT_SUPPORT_FLAG 0x04
+
struct detailed_data_monitor_range {
u8 min_vfreq;
u8 max_vfreq;
@@ -173,21 +182,23 @@ struct detailed_timing {
#define DRM_EDID_INPUT_BLANK_TO_BLACK (1 << 4)
#define DRM_EDID_INPUT_VIDEO_LEVEL (3 << 5)
#define DRM_EDID_INPUT_DIGITAL (1 << 7)
-#define DRM_EDID_DIGITAL_DEPTH_MASK (7 << 4)
-#define DRM_EDID_DIGITAL_DEPTH_UNDEF (0 << 4)
-#define DRM_EDID_DIGITAL_DEPTH_6 (1 << 4)
-#define DRM_EDID_DIGITAL_DEPTH_8 (2 << 4)
-#define DRM_EDID_DIGITAL_DEPTH_10 (3 << 4)
-#define DRM_EDID_DIGITAL_DEPTH_12 (4 << 4)
-#define DRM_EDID_DIGITAL_DEPTH_14 (5 << 4)
-#define DRM_EDID_DIGITAL_DEPTH_16 (6 << 4)
-#define DRM_EDID_DIGITAL_DEPTH_RSVD (7 << 4)
-#define DRM_EDID_DIGITAL_TYPE_UNDEF (0)
-#define DRM_EDID_DIGITAL_TYPE_DVI (1)
-#define DRM_EDID_DIGITAL_TYPE_HDMI_A (2)
-#define DRM_EDID_DIGITAL_TYPE_HDMI_B (3)
-#define DRM_EDID_DIGITAL_TYPE_MDDI (4)
-#define DRM_EDID_DIGITAL_TYPE_DP (5)
+#define DRM_EDID_DIGITAL_DEPTH_MASK (7 << 4) /* 1.4 */
+#define DRM_EDID_DIGITAL_DEPTH_UNDEF (0 << 4) /* 1.4 */
+#define DRM_EDID_DIGITAL_DEPTH_6 (1 << 4) /* 1.4 */
+#define DRM_EDID_DIGITAL_DEPTH_8 (2 << 4) /* 1.4 */
+#define DRM_EDID_DIGITAL_DEPTH_10 (3 << 4) /* 1.4 */
+#define DRM_EDID_DIGITAL_DEPTH_12 (4 << 4) /* 1.4 */
+#define DRM_EDID_DIGITAL_DEPTH_14 (5 << 4) /* 1.4 */
+#define DRM_EDID_DIGITAL_DEPTH_16 (6 << 4) /* 1.4 */
+#define DRM_EDID_DIGITAL_DEPTH_RSVD (7 << 4) /* 1.4 */
+#define DRM_EDID_DIGITAL_TYPE_MASK (7 << 0) /* 1.4 */
+#define DRM_EDID_DIGITAL_TYPE_UNDEF (0 << 0) /* 1.4 */
+#define DRM_EDID_DIGITAL_TYPE_DVI (1 << 0) /* 1.4 */
+#define DRM_EDID_DIGITAL_TYPE_HDMI_A (2 << 0) /* 1.4 */
+#define DRM_EDID_DIGITAL_TYPE_HDMI_B (3 << 0) /* 1.4 */
+#define DRM_EDID_DIGITAL_TYPE_MDDI (4 << 0) /* 1.4 */
+#define DRM_EDID_DIGITAL_TYPE_DP (5 << 0) /* 1.4 */
+#define DRM_EDID_DIGITAL_DFP_1_X (1 << 0) /* 1.3 */
#define DRM_EDID_FEATURE_DEFAULT_GTF (1 << 0)
#define DRM_EDID_FEATURE_PREFERRED_TIMING (1 << 1)
@@ -328,6 +339,7 @@ struct cea_sad {
struct drm_encoder;
struct drm_connector;
+struct drm_connector_state;
struct drm_display_mode;
int drm_edid_to_sad(struct edid *edid, struct cea_sad **sads);
@@ -349,18 +361,30 @@ drm_load_edid_firmware(struct drm_connector *connector)
int
drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
- const struct drm_display_mode *mode,
- bool is_hdmi2_sink);
+ struct drm_connector *connector,
+ const struct drm_display_mode *mode);
int
drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
struct drm_connector *connector,
const struct drm_display_mode *mode);
+
+void
+drm_hdmi_avi_infoframe_colorspace(struct hdmi_avi_infoframe *frame,
+ const struct drm_connector_state *conn_state);
+
+void
+drm_hdmi_avi_infoframe_bars(struct hdmi_avi_infoframe *frame,
+ const struct drm_connector_state *conn_state);
+
void
drm_hdmi_avi_infoframe_quant_range(struct hdmi_avi_infoframe *frame,
+ struct drm_connector *connector,
const struct drm_display_mode *mode,
- enum hdmi_quantization_range rgb_quant_range,
- bool rgb_quant_range_selectable,
- bool is_hdmi2_sink);
+ enum hdmi_quantization_range rgb_quant_range);
+
+int
+drm_hdmi_infoframe_set_hdr_metadata(struct hdmi_drm_infoframe *frame,
+ const struct drm_connector_state *conn_state);
/**
* drm_eld_mnl - Get ELD monitor name length in bytes.
@@ -466,10 +490,8 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid);
int drm_add_override_edid_modes(struct drm_connector *connector);
u8 drm_match_cea_mode(const struct drm_display_mode *to_match);
-enum hdmi_picture_aspect drm_get_cea_aspect_ratio(const u8 video_code);
bool drm_detect_hdmi_monitor(struct edid *edid);
bool drm_detect_monitor_audio(struct edid *edid);
-bool drm_rgb_quant_range_selectable(struct edid *edid);
enum hdmi_quantization_range
drm_default_rgb_quant_range(const struct drm_display_mode *mode);
int drm_add_modes_noedid(struct drm_connector *connector,
diff --git a/sys/dev/pci/drm/include/drm/drm_encoder.h b/sys/dev/pci/drm/include/drm/drm_encoder.h
index 4f597c0730b..4370e039c01 100644
--- a/sys/dev/pci/drm/include/drm/drm_encoder.h
+++ b/sys/dev/pci/drm/include/drm/drm_encoder.h
@@ -28,6 +28,7 @@
#include <drm/drm_crtc.h>
#include <drm/drm_mode.h>
#include <drm/drm_mode_object.h>
+#include <drm/drm_util.h>
struct drm_encoder;
@@ -139,7 +140,7 @@ struct drm_encoder {
* @possible_crtcs: Bitmask of potential CRTC bindings, using
* drm_crtc_index() as the index into the bitfield. The driver must set
* the bits for all &drm_crtc objects this encoder can be connected to
- * before calling drm_encoder_init().
+ * before calling drm_dev_register().
*
* In reality almost every driver gets this wrong.
*
@@ -153,7 +154,7 @@ struct drm_encoder {
* using drm_encoder_index() as the index into the bitfield. The driver
* must set the bits for all &drm_encoder objects which can clone a
* &drm_crtc together with this encoder before calling
- * drm_encoder_init(). Drivers should set the bit representing the
+ * drm_dev_register(). Drivers should set the bit representing the
* encoder itself, too. Cloning bits should be set such that when two
* encoders can be used in a cloned configuration, they both should have
* each another bits set.
@@ -171,7 +172,13 @@ struct drm_encoder {
* &drm_connector_state.crtc.
*/
struct drm_crtc *crtc;
- struct drm_bridge *bridge;
+
+ /**
+ * @bridge_chain: Bridges attached to this encoder. Drivers shall not
+ * access this field directly.
+ */
+ struct list_head bridge_chain;
+
const struct drm_encoder_funcs *funcs;
const struct drm_encoder_helper_funcs *helper_private;
};
@@ -197,7 +204,7 @@ static inline unsigned int drm_encoder_index(const struct drm_encoder *encoder)
}
/**
- * drm_encoder_mask - find the mask of a registered ENCODER
+ * drm_encoder_mask - find the mask of a registered encoder
* @encoder: encoder to find mask for
*
* Given a registered encoder, return the mask bit of that encoder for an
diff --git a/sys/dev/pci/drm/include/drm/drm_encoder_slave.h b/sys/dev/pci/drm/include/drm/drm_encoder_slave.h
new file mode 100644
index 00000000000..b2f01c11f8e
--- /dev/null
+++ b/sys/dev/pci/drm/include/drm/drm_encoder_slave.h
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __DRM_ENCODER_SLAVE_H__
+#define __DRM_ENCODER_SLAVE_H__
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_encoder.h>
+
+/**
+ * struct drm_encoder_slave_funcs - Entry points exposed by a slave encoder driver
+ * @set_config: Initialize any encoder-specific modesetting parameters.
+ * The meaning of the @params parameter is implementation
+ * dependent. It will usually be a structure with DVO port
+ * data format settings or timings. It's not required for
+ * the new parameters to take effect until the next mode
+ * is set.
+ *
+ * Most of its members are analogous to the function pointers in
+ * &drm_encoder_helper_funcs and they can optionally be used to
+ * initialize the latter. Connector-like methods (e.g. @get_modes and
+ * @set_property) will typically be wrapped around and only be called
+ * if the encoder is the currently selected one for the connector.
+ */
+struct drm_encoder_slave_funcs {
+ void (*set_config)(struct drm_encoder *encoder,
+ void *params);
+
+ void (*destroy)(struct drm_encoder *encoder);
+ void (*dpms)(struct drm_encoder *encoder, int mode);
+ void (*save)(struct drm_encoder *encoder);
+ void (*restore)(struct drm_encoder *encoder);
+ bool (*mode_fixup)(struct drm_encoder *encoder,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
+ int (*mode_valid)(struct drm_encoder *encoder,
+ struct drm_display_mode *mode);
+ void (*mode_set)(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
+
+ enum drm_connector_status (*detect)(struct drm_encoder *encoder,
+ struct drm_connector *connector);
+ int (*get_modes)(struct drm_encoder *encoder,
+ struct drm_connector *connector);
+ int (*create_resources)(struct drm_encoder *encoder,
+ struct drm_connector *connector);
+ int (*set_property)(struct drm_encoder *encoder,
+ struct drm_connector *connector,
+ struct drm_property *property,
+ uint64_t val);
+
+};
+
+/**
+ * struct drm_encoder_slave - Slave encoder struct
+ * @base: DRM encoder object.
+ * @slave_funcs: Slave encoder callbacks.
+ * @slave_priv: Slave encoder private data.
+ * @bus_priv: Bus specific data.
+ *
+ * A &drm_encoder_slave has two sets of callbacks, @slave_funcs and the
+ * ones in @base. The former are never actually called by the common
+ * CRTC code, it's just a convenience for splitting the encoder
+ * functions in an upper, GPU-specific layer and a (hopefully)
+ * GPU-agnostic lower layer: It's the GPU driver responsibility to
+ * call the slave methods when appropriate.
+ *
+ * drm_i2c_encoder_init() provides a way to get an implementation of
+ * this.
+ */
+struct drm_encoder_slave {
+ struct drm_encoder base;
+
+ const struct drm_encoder_slave_funcs *slave_funcs;
+ void *slave_priv;
+ void *bus_priv;
+};
+#define to_encoder_slave(x) container_of((x), struct drm_encoder_slave, base)
+
+#ifdef notyet
+int drm_i2c_encoder_init(struct drm_device *dev,
+ struct drm_encoder_slave *encoder,
+ struct i2c_adapter *adap,
+ const struct i2c_board_info *info);
+#endif
+
+/**
+ * struct drm_i2c_encoder_driver
+ *
+ * Describes a device driver for an encoder connected to the GPU
+ * through an I2C bus. In addition to the entry points in @i2c_driver
+ * an @encoder_init function should be provided. It will be called to
+ * give the driver an opportunity to allocate any per-encoder data
+ * structures and to initialize the @slave_funcs and (optionally)
+ * @slave_priv members of @encoder.
+ */
+struct drm_i2c_encoder_driver {
+#ifdef notyet
+ struct i2c_driver i2c_driver;
+
+ int (*encoder_init)(struct i2c_client *client,
+ struct drm_device *dev,
+ struct drm_encoder_slave *encoder);
+#endif
+
+};
+#define to_drm_i2c_encoder_driver(x) container_of((x), \
+ struct drm_i2c_encoder_driver, \
+ i2c_driver)
+
+/**
+ * drm_i2c_encoder_get_client - Get the I2C client corresponding to an encoder
+ */
+static inline struct i2c_client *drm_i2c_encoder_get_client(struct drm_encoder *encoder)
+{
+ return (struct i2c_client *)to_encoder_slave(encoder)->bus_priv;
+}
+
+/**
+ * drm_i2c_encoder_register - Register an I2C encoder driver
+ * @owner: Module containing the driver.
+ * @driver: Driver to be registered.
+ */
+static inline int drm_i2c_encoder_register(struct module *owner,
+ struct drm_i2c_encoder_driver *driver)
+{
+ STUB();
+ return -ENOSYS;
+#ifdef notyet
+ return i2c_register_driver(owner, &driver->i2c_driver);
+#endif
+}
+
+/**
+ * drm_i2c_encoder_unregister - Unregister an I2C encoder driver
+ * @driver: Driver to be unregistered.
+ */
+static inline void drm_i2c_encoder_unregister(struct drm_i2c_encoder_driver *driver)
+{
+ STUB();
+#ifdef notyet
+ i2c_del_driver(&driver->i2c_driver);
+#endif
+}
+
+void drm_i2c_encoder_destroy(struct drm_encoder *encoder);
+
+
+/*
+ * Wrapper fxns which can be plugged in to drm_encoder_helper_funcs:
+ */
+
+void drm_i2c_encoder_dpms(struct drm_encoder *encoder, int mode);
+bool drm_i2c_encoder_mode_fixup(struct drm_encoder *encoder,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
+void drm_i2c_encoder_prepare(struct drm_encoder *encoder);
+void drm_i2c_encoder_commit(struct drm_encoder *encoder);
+void drm_i2c_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
+enum drm_connector_status drm_i2c_encoder_detect(struct drm_encoder *encoder,
+ struct drm_connector *connector);
+void drm_i2c_encoder_save(struct drm_encoder *encoder);
+void drm_i2c_encoder_restore(struct drm_encoder *encoder);
+
+
+#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_fb_helper.h b/sys/dev/pci/drm/include/drm/drm_fb_helper.h
index 51e82c7372d..cc41a73707a 100644
--- a/sys/dev/pci/drm/include/drm/drm_fb_helper.h
+++ b/sys/dev/pci/drm/include/drm/drm_fb_helper.h
@@ -32,29 +32,17 @@
struct drm_fb_helper;
-#ifdef notyet
#include <drm/drm_client.h>
-#endif
#include <drm/drm_crtc.h>
#include <drm/drm_device.h>
#include <linux/kgdb.h>
+#include <linux/vgaarb.h>
enum mode_set_atomic {
LEAVE_ATOMIC_MODE_SET,
ENTER_ATOMIC_MODE_SET,
};
-struct drm_fb_offset {
- int x, y;
-};
-
-struct drm_fb_helper_crtc {
- struct drm_mode_set mode_set;
- struct drm_display_mode *desired_mode;
- int x, y;
- int rotation;
-};
-
/**
* struct drm_fb_helper_surface_size - describes fbdev size and scanout surface size
* @fb_width: fbdev width
@@ -69,10 +57,8 @@ struct drm_fb_helper_crtc {
* according to the largest width/height (so it is large enough for all CRTCs
* to scanout). But the fbdev width/height is sized to the minimum width/
* height of all the displays. This ensures that fbcon fits on the smallest
- * of the attached displays.
- *
- * So what is passed to drm_fb_helper_fill_var() should be fb_width/fb_height,
- * rather than the surface size.
+ * of the attached displays. fb_width/fb_height is used by
+ * drm_fb_helper_fill_info() to fill out the &fb_info.var structure.
*/
struct drm_fb_helper_surface_size {
u32 fb_width;
@@ -105,43 +91,12 @@ struct drm_fb_helper_funcs {
*/
int (*fb_probe)(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes);
-
- /**
- * @initial_config:
- *
- * Driver callback to setup an initial fbdev display configuration.
- * Drivers can use this callback to tell the fbdev emulation what the
- * preferred initial configuration is. This is useful to implement
- * smooth booting where the fbdev (and subsequently all userspace) never
- * changes the mode, but always inherits the existing configuration.
- *
- * This callback is optional.
- *
- * RETURNS:
- *
- * The driver should return true if a suitable initial configuration has
- * been filled out and false when the fbdev helper should fall back to
- * the default probing logic.
- */
- bool (*initial_config)(struct drm_fb_helper *fb_helper,
- struct drm_fb_helper_crtc **crtcs,
- struct drm_display_mode **modes,
- struct drm_fb_offset *offsets,
- bool *enabled, int width, int height);
-};
-
-struct drm_fb_helper_connector {
- struct drm_connector *connector;
};
/**
* struct drm_fb_helper - main structure to emulate fbdev on top of KMS
* @fb: Scanout framebuffer object
* @dev: DRM device
- * @crtc_count: number of possible CRTCs
- * @crtc_info: per-CRTC helper state (mode, x/y offset, etc)
- * @connector_count: number of connected connectors
- * @connector_info_alloc_count: size of connector_info
* @funcs: driver callbacks for fb helper
* @fbdev: emulated fbdev device info struct
* @pseudo_palette: fake palette of 16 colors
@@ -162,9 +117,7 @@ struct drm_fb_helper {
*
* DRM client used by the generic fbdev emulation.
*/
-#ifdef notyet
struct drm_client_dev client;
-#endif
/**
* @buffer:
@@ -175,24 +128,6 @@ struct drm_fb_helper {
struct drm_framebuffer *fb;
struct drm_device *dev;
- int crtc_count;
- struct drm_fb_helper_crtc *crtc_info;
- int connector_count;
- int connector_info_alloc_count;
- /**
- * @sw_rotations:
- * Bitmask of all rotations requested for panel-orientation which
- * could not be handled in hardware. If only one bit is set
- * fbdev->fbcon_rotate_hint gets set to the requested rotation.
- */
- int sw_rotations;
- /**
- * @connector_info:
- *
- * Array of per-connector information. Do not iterate directly, but use
- * drm_fb_helper_for_each_connector.
- */
- struct drm_fb_helper_connector **connector_info;
const struct drm_fb_helper_funcs *funcs;
struct fb_info *fbdev;
u32 pseudo_palette[17];
@@ -253,13 +188,11 @@ struct drm_fb_helper {
int preferred_bpp;
};
-#ifdef notyet
static inline struct drm_fb_helper *
drm_fb_helper_from_client(struct drm_client_dev *client)
{
return container_of(client, struct drm_fb_helper, client);
}
-#endif
/**
* define DRM_FB_HELPER_DEFAULT_OPS - helper define for drm drivers
@@ -280,8 +213,7 @@ drm_fb_helper_from_client(struct drm_client_dev *client)
#ifdef CONFIG_DRM_FBDEV_EMULATION
void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
const struct drm_fb_helper_funcs *funcs);
-int drm_fb_helper_init(struct drm_device *dev,
- struct drm_fb_helper *helper, int max_conn);
+int drm_fb_helper_init(struct drm_device *dev, struct drm_fb_helper *helper);
void drm_fb_helper_fini(struct drm_fb_helper *helper);
int drm_fb_helper_blank(int blank, struct fb_info *info);
int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
@@ -294,16 +226,12 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper);
struct fb_info *drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper);
void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper);
-void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper,
- uint32_t fb_width, uint32_t fb_height);
-void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
- uint32_t depth);
-
-void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper);
+void drm_fb_helper_fill_info(struct fb_info *info,
+ struct drm_fb_helper *fb_helper,
+ struct drm_fb_helper_surface_size *sizes);
void drm_fb_helper_deferred_io(struct fb_info *info,
struct list_head *pagelist);
-int drm_fb_helper_defio_init(struct drm_fb_helper *fb_helper);
ssize_t drm_fb_helper_sys_read(struct fb_info *info, char __user *buf,
size_t count, loff_t *ppos);
@@ -335,31 +263,12 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper);
int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel);
-int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper);
int drm_fb_helper_debug_enter(struct fb_info *info);
int drm_fb_helper_debug_leave(struct fb_info *info);
-struct drm_display_mode *
-drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector,
- int width, int height);
-struct drm_display_mode *
-drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn);
-
-int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector);
-int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
- struct drm_connector *connector);
-
-int drm_fb_helper_fbdev_setup(struct drm_device *dev,
- struct drm_fb_helper *fb_helper,
- const struct drm_fb_helper_funcs *funcs,
- unsigned int preferred_bpp,
- unsigned int max_conn_count);
-void drm_fb_helper_fbdev_teardown(struct drm_device *dev);
void drm_fb_helper_lastclose(struct drm_device *dev);
void drm_fb_helper_output_poll_changed(struct drm_device *dev);
-int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
- struct drm_fb_helper_surface_size *sizes);
int drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp);
#else
static inline void drm_fb_helper_prepare(struct drm_device *dev,
@@ -369,8 +278,7 @@ static inline void drm_fb_helper_prepare(struct drm_device *dev,
}
static inline int drm_fb_helper_init(struct drm_device *dev,
- struct drm_fb_helper *helper,
- int max_conn)
+ struct drm_fb_helper *helper)
{
/* So drivers can use it to free the struct */
helper->dev = dev;
@@ -423,14 +331,10 @@ static inline void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper)
{
}
-static inline void drm_fb_helper_fill_var(struct fb_info *info,
- struct drm_fb_helper *fb_helper,
- uint32_t fb_width, uint32_t fb_height)
-{
-}
-
-static inline void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
- uint32_t depth)
+static inline void
+drm_fb_helper_fill_info(struct fb_info *info,
+ struct drm_fb_helper *fb_helper,
+ struct drm_fb_helper_surface_size *sizes)
{
}
@@ -446,10 +350,6 @@ static inline int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
return 0;
}
-static inline void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper)
-{
-}
-
static inline void drm_fb_helper_deferred_io(struct fb_info *info,
struct list_head *pagelist)
{
@@ -525,12 +425,6 @@ static inline int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper,
return 0;
}
-static inline int
-drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
-{
- return 0;
-}
-
static inline int drm_fb_helper_debug_enter(struct fb_info *info)
{
return 0;
@@ -541,52 +435,6 @@ static inline int drm_fb_helper_debug_leave(struct fb_info *info)
return 0;
}
-static inline struct drm_display_mode *
-drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector,
- int width, int height)
-{
- return NULL;
-}
-
-static inline struct drm_display_mode *
-drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
- int width, int height)
-{
- return NULL;
-}
-
-static inline int
-drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
- struct drm_connector *connector)
-{
- return 0;
-}
-
-static inline int
-drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
- struct drm_connector *connector)
-{
- return 0;
-}
-
-static inline int
-drm_fb_helper_fbdev_setup(struct drm_device *dev,
- struct drm_fb_helper *fb_helper,
- const struct drm_fb_helper_funcs *funcs,
- unsigned int preferred_bpp,
- unsigned int max_conn_count)
-{
- /* So drivers can use it to free the struct */
- dev->fb_helper = fb_helper;
-
- return 0;
-}
-
-static inline void drm_fb_helper_fbdev_teardown(struct drm_device *dev)
-{
- dev->fb_helper = NULL;
-}
-
static inline void drm_fb_helper_lastclose(struct drm_device *dev)
{
}
@@ -596,13 +444,6 @@ static inline void drm_fb_helper_output_poll_changed(struct drm_device *dev)
}
static inline int
-drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
- struct drm_fb_helper_surface_size *sizes)
-{
- return 0;
-}
-
-static inline int
drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
{
return 0;
@@ -610,7 +451,16 @@ drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
#endif
-#ifdef __linux__
+/**
+ * drm_fb_helper_remove_conflicting_framebuffers - remove firmware-configured framebuffers
+ * @a: memory range, users of which are to be removed
+ * @name: requesting driver name
+ * @primary: also kick vga16fb if present
+ *
+ * This function removes framebuffer devices (initialized by firmware/bootloader)
+ * which use memory range described by @a. If @a is NULL all such devices are
+ * removed.
+ */
static inline int
drm_fb_helper_remove_conflicting_framebuffers(struct apertures_struct *a,
const char *name, bool primary)
@@ -621,6 +471,34 @@ drm_fb_helper_remove_conflicting_framebuffers(struct apertures_struct *a,
return 0;
#endif
}
-#endif /* __linux__ */
+
+/**
+ * drm_fb_helper_remove_conflicting_pci_framebuffers - remove firmware-configured framebuffers for PCI devices
+ * @pdev: PCI device
+ * @name: requesting driver name
+ *
+ * This function removes framebuffer devices (eg. initialized by firmware)
+ * using memory range configured for any of @pdev's memory bars.
+ *
+ * The function assumes that PCI device with shadowed ROM drives a primary
+ * display and so kicks out vga16fb.
+ */
+static inline int
+drm_fb_helper_remove_conflicting_pci_framebuffers(struct pci_dev *pdev,
+ const char *name)
+{
+ int ret = 0;
+
+ /*
+ * WARNING: Apparently we must kick fbdev drivers before vgacon,
+ * otherwise the vga fbdev driver falls over.
+ */
+#if IS_REACHABLE(CONFIG_FB)
+ ret = remove_conflicting_pci_framebuffers(pdev, name);
+#endif
+ if (ret == 0)
+ ret = vga_remove_vgacon(pdev);
+ return ret;
+}
#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_file.h b/sys/dev/pci/drm/include/drm/drm_file.h
index a2914170635..14017314421 100644
--- a/sys/dev/pci/drm/include/drm/drm_file.h
+++ b/sys/dev/pci/drm/include/drm/drm_file.h
@@ -30,18 +30,21 @@
#ifndef _DRM_FILE_H_
#define _DRM_FILE_H_
-#include <sys/selinfo.h>
#include <linux/types.h>
#include <linux/completion.h>
+#include <linux/idr.h>
#include <uapi/drm/drm.h>
#include <drm/drm_prime.h>
+#include <sys/selinfo.h>
+
struct dma_fence;
struct drm_file;
struct drm_device;
struct device;
+struct file;
/*
* FIXME: Not sure we want to have drm_minor here in the end, but to avoid
@@ -70,7 +73,9 @@ struct drm_minor {
/* private: */
int index; /* Minor device number */
int type; /* Control or render */
+#ifdef __linux__
struct device *kdev; /* Linux device */
+#endif
struct drm_device *dev;
struct dentry *debugfs_root;
@@ -165,14 +170,14 @@ struct drm_file {
* See also the :ref:`section on primary nodes and authentication
* <drm_primary_node>`.
*/
- unsigned authenticated :1;
+ bool authenticated;
/**
* @stereo_allowed:
*
* True when the client has asked us to expose stereo 3D mode flags.
*/
- unsigned stereo_allowed :1;
+ bool stereo_allowed;
/**
* @universal_planes:
@@ -180,10 +185,10 @@ struct drm_file {
* True if client understands CRTC primary planes and cursor planes
* in the plane list. Automatically set when @atomic is set.
*/
- unsigned universal_planes:1;
+ bool universal_planes;
/** @atomic: True if client understands atomic properties. */
- unsigned atomic:1;
+ bool atomic;
/**
* @aspect_ratio_allowed:
@@ -191,14 +196,14 @@ struct drm_file {
* True, if client can handle picture aspect ratios, and has requested
* to pass this information along with the mode.
*/
- unsigned aspect_ratio_allowed:1;
+ bool aspect_ratio_allowed;
/**
* @writeback_connectors:
*
* True if client understands writeback connectors
*/
- unsigned writeback_connectors:1;
+ bool writeback_connectors;
/**
* @is_master:
@@ -209,7 +214,7 @@ struct drm_file {
* See also the :ref:`section on primary nodes and authentication
* <drm_primary_node>`.
*/
- unsigned is_master:1;
+ bool is_master;
/**
* @master:
@@ -238,12 +243,9 @@ struct drm_file {
struct list_head lhead;
/** @minor: &struct drm_minor for this file. */
-#ifdef notyet
struct drm_minor *minor;
-#else
- int minor;
- int minor_type;
-#endif
+
+ int fminor;
/**
* @object_idr:
@@ -340,7 +342,9 @@ struct drm_file {
struct drm_prime_file_private prime;
/* private: */
+#if IS_ENABLED(CONFIG_DRM_LEGACY)
unsigned long lock_count; /* DRI1 legacy lock count */
+#endif
struct selinfo rsel;
SPLAY_ENTRY(drm_file) link;
@@ -358,11 +362,7 @@ struct drm_file {
*/
static inline bool drm_is_primary_client(const struct drm_file *file_priv)
{
-#ifdef __linux__
return file_priv->minor->type == DRM_MINOR_PRIMARY;
-#else
- return file_priv->minor_type == DRM_MINOR_PRIMARY;
-#endif
}
/**
@@ -376,11 +376,7 @@ static inline bool drm_is_primary_client(const struct drm_file *file_priv)
*/
static inline bool drm_is_render_client(const struct drm_file *file_priv)
{
-#ifdef __linux__
return file_priv->minor->type == DRM_MINOR_RENDER;
-#else
- return file_priv->minor_type == DRM_MINOR_RENDER;
-#endif
}
#ifdef __linux__
@@ -388,6 +384,7 @@ int drm_open(struct inode *inode, struct file *filp);
ssize_t drm_read(struct file *filp, char __user *buffer,
size_t count, loff_t *offset);
int drm_release(struct inode *inode, struct file *filp);
+int drm_release_noglobal(struct inode *inode, struct file *filp);
__poll_t drm_poll(struct file *filp, struct poll_table_struct *wait);
#endif
int drm_event_reserve_init_locked(struct drm_device *dev,
@@ -403,4 +400,15 @@ void drm_event_cancel_free(struct drm_device *dev,
void drm_send_event_locked(struct drm_device *dev, struct drm_pending_event *e);
void drm_send_event(struct drm_device *dev, struct drm_pending_event *e);
+struct file *mock_drm_getfile(struct drm_minor *minor, unsigned int flags);
+
+#ifdef CONFIG_MMU
+struct drm_vma_offset_manager;
+unsigned long drm_get_unmapped_area(struct file *file,
+ unsigned long uaddr, unsigned long len,
+ unsigned long pgoff, unsigned long flags,
+ struct drm_vma_offset_manager *mgr);
+#endif /* CONFIG_MMU */
+
+
#endif /* _DRM_FILE_H_ */
diff --git a/sys/dev/pci/drm/include/drm/drm_flip_work.h b/sys/dev/pci/drm/include/drm/drm_flip_work.h
new file mode 100644
index 00000000000..21c3d512d25
--- /dev/null
+++ b/sys/dev/pci/drm/include/drm/drm_flip_work.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef DRM_FLIP_WORK_H
+#define DRM_FLIP_WORK_H
+
+#include <linux/kfifo.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+
+/**
+ * DOC: flip utils
+ *
+ * Util to queue up work to run from work-queue context after flip/vblank.
+ * Typically this can be used to defer unref of framebuffer's, cursor
+ * bo's, etc until after vblank. The APIs are all thread-safe.
+ * Moreover, drm_flip_work_queue_task and drm_flip_work_queue can be called
+ * in atomic context.
+ */
+
+struct drm_flip_work;
+
+/*
+ * drm_flip_func_t - callback function
+ *
+ * @work: the flip work
+ * @val: value queued via drm_flip_work_queue()
+ *
+ * Callback function to be called for each of the queue'd work items after
+ * drm_flip_work_commit() is called.
+ */
+typedef void (*drm_flip_func_t)(struct drm_flip_work *work, void *val);
+
+/**
+ * struct drm_flip_task - flip work task
+ * @node: list entry element
+ * @data: data to pass to &drm_flip_work.func
+ */
+struct drm_flip_task {
+ struct list_head node;
+ void *data;
+};
+
+/**
+ * struct drm_flip_work - flip work queue
+ * @name: debug name
+ * @func: callback fxn called for each committed item
+ * @worker: worker which calls @func
+ * @queued: queued tasks
+ * @commited: commited tasks
+ * @lock: lock to access queued and commited lists
+ */
+struct drm_flip_work {
+ const char *name;
+ drm_flip_func_t func;
+ struct work_struct worker;
+ struct list_head queued;
+ struct list_head commited;
+ spinlock_t lock;
+};
+
+struct drm_flip_task *drm_flip_work_allocate_task(void *data, gfp_t flags);
+void drm_flip_work_queue_task(struct drm_flip_work *work,
+ struct drm_flip_task *task);
+void drm_flip_work_queue(struct drm_flip_work *work, void *val);
+void drm_flip_work_commit(struct drm_flip_work *work,
+ struct workqueue_struct *wq);
+void drm_flip_work_init(struct drm_flip_work *work,
+ const char *name, drm_flip_func_t func);
+void drm_flip_work_cleanup(struct drm_flip_work *work);
+
+#endif /* DRM_FLIP_WORK_H */
diff --git a/sys/dev/pci/drm/include/drm/drm_format_helper.h b/sys/dev/pci/drm/include/drm/drm_format_helper.h
new file mode 100644
index 00000000000..7c5d4ffb2af
--- /dev/null
+++ b/sys/dev/pci/drm/include/drm/drm_format_helper.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 or MIT */
+/*
+ * Copyright (C) 2016 Noralf Trønnes
+ */
+
+#ifndef __LINUX_DRM_FORMAT_HELPER_H
+#define __LINUX_DRM_FORMAT_HELPER_H
+
+struct drm_framebuffer;
+struct drm_rect;
+
+void drm_fb_memcpy(void *dst, void *vaddr, struct drm_framebuffer *fb,
+ struct drm_rect *clip);
+void drm_fb_memcpy_dstclip(void __iomem *dst, void *vaddr,
+ struct drm_framebuffer *fb,
+ struct drm_rect *clip);
+void drm_fb_swab16(u16 *dst, void *vaddr, struct drm_framebuffer *fb,
+ struct drm_rect *clip);
+void drm_fb_xrgb8888_to_rgb565(void *dst, void *vaddr,
+ struct drm_framebuffer *fb,
+ struct drm_rect *clip, bool swab);
+void drm_fb_xrgb8888_to_rgb565_dstclip(void __iomem *dst, unsigned int dst_pitch,
+ void *vaddr, struct drm_framebuffer *fb,
+ struct drm_rect *clip, bool swab);
+void drm_fb_xrgb8888_to_rgb888_dstclip(void __iomem *dst, unsigned int dst_pitch,
+ void *vaddr, struct drm_framebuffer *fb,
+ struct drm_rect *clip);
+void drm_fb_xrgb8888_to_gray8(u8 *dst, void *vaddr, struct drm_framebuffer *fb,
+ struct drm_rect *clip);
+
+#endif /* __LINUX_DRM_FORMAT_HELPER_H */
diff --git a/sys/dev/pci/drm/include/drm/drm_fourcc.h b/sys/dev/pci/drm/include/drm/drm_fourcc.h
index f9c15845f46..156b122c0ad 100644
--- a/sys/dev/pci/drm/include/drm/drm_fourcc.h
+++ b/sys/dev/pci/drm/include/drm/drm_fourcc.h
@@ -25,30 +25,113 @@
#include <linux/types.h>
#include <uapi/drm/drm_fourcc.h>
+/*
+ * DRM formats are little endian. Define host endian variants for the
+ * most common formats here, to reduce the #ifdefs needed in drivers.
+ *
+ * Note that the DRM_FORMAT_BIG_ENDIAN flag should only be used in
+ * case the format can't be specified otherwise, so we don't end up
+ * with two values describing the same format.
+ */
+#ifdef __BIG_ENDIAN
+# define DRM_FORMAT_HOST_XRGB1555 (DRM_FORMAT_XRGB1555 | \
+ DRM_FORMAT_BIG_ENDIAN)
+# define DRM_FORMAT_HOST_RGB565 (DRM_FORMAT_RGB565 | \
+ DRM_FORMAT_BIG_ENDIAN)
+# define DRM_FORMAT_HOST_XRGB8888 DRM_FORMAT_BGRX8888
+# define DRM_FORMAT_HOST_ARGB8888 DRM_FORMAT_BGRA8888
+#else
+# define DRM_FORMAT_HOST_XRGB1555 DRM_FORMAT_XRGB1555
+# define DRM_FORMAT_HOST_RGB565 DRM_FORMAT_RGB565
+# define DRM_FORMAT_HOST_XRGB8888 DRM_FORMAT_XRGB8888
+# define DRM_FORMAT_HOST_ARGB8888 DRM_FORMAT_ARGB8888
+#endif
+
struct drm_device;
struct drm_mode_fb_cmd2;
/**
* struct drm_format_info - information about a DRM format
- * @format: 4CC format identifier (DRM_FORMAT_*)
- * @depth: Color depth (number of bits per pixel excluding padding bits),
- * valid for a subset of RGB formats only. This is a legacy field, do not
- * use in new code and set to 0 for new formats.
- * @num_planes: Number of color planes (1 to 3)
- * @cpp: Number of bytes per pixel (per plane)
- * @hsub: Horizontal chroma subsampling factor
- * @vsub: Vertical chroma subsampling factor
- * @has_alpha: Does the format embeds an alpha component?
- * @is_yuv: Is it a YUV format?
*/
struct drm_format_info {
+ /** @format: 4CC format identifier (DRM_FORMAT_*) */
u32 format;
+
+ /**
+ * @depth:
+ *
+ * Color depth (number of bits per pixel excluding padding bits),
+ * valid for a subset of RGB formats only. This is a legacy field, do
+ * not use in new code and set to 0 for new formats.
+ */
u8 depth;
+
+ /** @num_planes: Number of color planes (1 to 3) */
u8 num_planes;
- u8 cpp[3];
+
+ union {
+ /**
+ * @cpp:
+ *
+ * Number of bytes per pixel (per plane), this is aliased with
+ * @char_per_block. It is deprecated in favour of using the
+ * triplet @char_per_block, @block_w, @block_h for better
+ * describing the pixel format.
+ */
+ u8 cpp[4];
+
+ /**
+ * @char_per_block:
+ *
+ * Number of bytes per block (per plane), where blocks are
+ * defined as a rectangle of pixels which are stored next to
+ * each other in a byte aligned memory region. Together with
+ * @block_w and @block_h this is used to properly describe tiles
+ * in tiled formats or to describe groups of pixels in packed
+ * formats for which the memory needed for a single pixel is not
+ * byte aligned.
+ *
+ * @cpp has been kept for historical reasons because there are
+ * a lot of places in drivers where it's used. In drm core for
+ * generic code paths the preferred way is to use
+ * @char_per_block, drm_format_info_block_width() and
+ * drm_format_info_block_height() which allows handling both
+ * block and non-block formats in the same way.
+ *
+ * For formats that are intended to be used only with non-linear
+ * modifiers both @cpp and @char_per_block must be 0 in the
+ * generic format table. Drivers could supply accurate
+ * information from their drm_mode_config.get_format_info hook
+ * if they want the core to be validating the pitch.
+ */
+ u8 char_per_block[4];
+ };
+
+ /**
+ * @block_w:
+ *
+ * Block width in pixels, this is intended to be accessed through
+ * drm_format_info_block_width()
+ */
+ u8 block_w[4];
+
+ /**
+ * @block_h:
+ *
+ * Block height in pixels, this is intended to be accessed through
+ * drm_format_info_block_height()
+ */
+ u8 block_h[4];
+
+ /** @hsub: Horizontal chroma subsampling factor */
u8 hsub;
+ /** @vsub: Vertical chroma subsampling factor */
u8 vsub;
+
+ /** @has_alpha: Does the format embeds an alpha component? */
bool has_alpha;
+
+ /** @is_yuv: Is it a YUV format? */
bool is_yuv;
};
@@ -60,18 +143,181 @@ struct drm_format_name_buf {
char str[32];
};
+/**
+ * drm_format_info_is_yuv_packed - check that the format info matches a YUV
+ * format with data laid in a single plane
+ * @info: format info
+ *
+ * Returns:
+ * A boolean indicating whether the format info matches a packed YUV format.
+ */
+static inline bool
+drm_format_info_is_yuv_packed(const struct drm_format_info *info)
+{
+ return info->is_yuv && info->num_planes == 1;
+}
+
+/**
+ * drm_format_info_is_yuv_semiplanar - check that the format info matches a YUV
+ * format with data laid in two planes (luminance and chrominance)
+ * @info: format info
+ *
+ * Returns:
+ * A boolean indicating whether the format info matches a semiplanar YUV format.
+ */
+static inline bool
+drm_format_info_is_yuv_semiplanar(const struct drm_format_info *info)
+{
+ return info->is_yuv && info->num_planes == 2;
+}
+
+/**
+ * drm_format_info_is_yuv_planar - check that the format info matches a YUV
+ * format with data laid in three planes (one for each YUV component)
+ * @info: format info
+ *
+ * Returns:
+ * A boolean indicating whether the format info matches a planar YUV format.
+ */
+static inline bool
+drm_format_info_is_yuv_planar(const struct drm_format_info *info)
+{
+ return info->is_yuv && info->num_planes == 3;
+}
+
+/**
+ * drm_format_info_is_yuv_sampling_410 - check that the format info matches a
+ * YUV format with 4:1:0 sub-sampling
+ * @info: format info
+ *
+ * Returns:
+ * A boolean indicating whether the format info matches a YUV format with 4:1:0
+ * sub-sampling.
+ */
+static inline bool
+drm_format_info_is_yuv_sampling_410(const struct drm_format_info *info)
+{
+ return info->is_yuv && info->hsub == 4 && info->vsub == 4;
+}
+
+/**
+ * drm_format_info_is_yuv_sampling_411 - check that the format info matches a
+ * YUV format with 4:1:1 sub-sampling
+ * @info: format info
+ *
+ * Returns:
+ * A boolean indicating whether the format info matches a YUV format with 4:1:1
+ * sub-sampling.
+ */
+static inline bool
+drm_format_info_is_yuv_sampling_411(const struct drm_format_info *info)
+{
+ return info->is_yuv && info->hsub == 4 && info->vsub == 1;
+}
+
+/**
+ * drm_format_info_is_yuv_sampling_420 - check that the format info matches a
+ * YUV format with 4:2:0 sub-sampling
+ * @info: format info
+ *
+ * Returns:
+ * A boolean indicating whether the format info matches a YUV format with 4:2:0
+ * sub-sampling.
+ */
+static inline bool
+drm_format_info_is_yuv_sampling_420(const struct drm_format_info *info)
+{
+ return info->is_yuv && info->hsub == 2 && info->vsub == 2;
+}
+
+/**
+ * drm_format_info_is_yuv_sampling_422 - check that the format info matches a
+ * YUV format with 4:2:2 sub-sampling
+ * @info: format info
+ *
+ * Returns:
+ * A boolean indicating whether the format info matches a YUV format with 4:2:2
+ * sub-sampling.
+ */
+static inline bool
+drm_format_info_is_yuv_sampling_422(const struct drm_format_info *info)
+{
+ return info->is_yuv && info->hsub == 2 && info->vsub == 1;
+}
+
+/**
+ * drm_format_info_is_yuv_sampling_444 - check that the format info matches a
+ * YUV format with 4:4:4 sub-sampling
+ * @info: format info
+ *
+ * Returns:
+ * A boolean indicating whether the format info matches a YUV format with 4:4:4
+ * sub-sampling.
+ */
+static inline bool
+drm_format_info_is_yuv_sampling_444(const struct drm_format_info *info)
+{
+ return info->is_yuv && info->hsub == 1 && info->vsub == 1;
+}
+
+/**
+ * drm_format_info_plane_width - width of the plane given the first plane
+ * @info: pixel format info
+ * @width: width of the first plane
+ * @plane: plane index
+ *
+ * Returns:
+ * The width of @plane, given that the width of the first plane is @width.
+ */
+static inline
+int drm_format_info_plane_width(const struct drm_format_info *info, int width,
+ int plane)
+{
+ if (!info || plane >= info->num_planes)
+ return 0;
+
+ if (plane == 0)
+ return width;
+
+ return width / info->hsub;
+}
+
+/**
+ * drm_format_info_plane_height - height of the plane given the first plane
+ * @info: pixel format info
+ * @height: height of the first plane
+ * @plane: plane index
+ *
+ * Returns:
+ * The height of @plane, given that the height of the first plane is @height.
+ */
+static inline
+int drm_format_info_plane_height(const struct drm_format_info *info, int height,
+ int plane)
+{
+ if (!info || plane >= info->num_planes)
+ return 0;
+
+ if (plane == 0)
+ return height;
+
+ return height / info->vsub;
+}
+
const struct drm_format_info *__drm_format_info(u32 format);
const struct drm_format_info *drm_format_info(u32 format);
const struct drm_format_info *
drm_get_format_info(struct drm_device *dev,
const struct drm_mode_fb_cmd2 *mode_cmd);
uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth);
-int drm_format_num_planes(uint32_t format);
-int drm_format_plane_cpp(uint32_t format, int plane);
-int drm_format_horz_chroma_subsampling(uint32_t format);
-int drm_format_vert_chroma_subsampling(uint32_t format);
-int drm_format_plane_width(int width, uint32_t format, int plane);
-int drm_format_plane_height(int height, uint32_t format, int plane);
+uint32_t drm_driver_legacy_fb_format(struct drm_device *dev,
+ uint32_t bpp, uint32_t depth);
+unsigned int drm_format_info_block_width(const struct drm_format_info *info,
+ int plane);
+unsigned int drm_format_info_block_height(const struct drm_format_info *info,
+ int plane);
+uint64_t drm_format_info_min_pitch(const struct drm_format_info *info,
+ int plane, unsigned int buffer_width);
const char *drm_get_format_name(uint32_t format, struct drm_format_name_buf *buf);
#endif /* __DRM_FOURCC_H__ */
diff --git a/sys/dev/pci/drm/include/drm/drm_framebuffer.h b/sys/dev/pci/drm/include/drm/drm_framebuffer.h
index c50502c656e..c0e0256e3e9 100644
--- a/sys/dev/pci/drm/include/drm/drm_framebuffer.h
+++ b/sys/dev/pci/drm/include/drm/drm_framebuffer.h
@@ -23,13 +23,18 @@
#ifndef __DRM_FRAMEBUFFER_H__
#define __DRM_FRAMEBUFFER_H__
-#include <linux/list.h>
#include <linux/ctype.h>
+#include <linux/list.h>
+#include <linux/sched.h>
+
#include <drm/drm_mode_object.h>
-struct drm_framebuffer;
-struct drm_file;
+struct drm_clip_rect;
struct drm_device;
+struct drm_file;
+struct drm_format_info;
+struct drm_framebuffer;
+struct drm_gem_object;
/**
* struct drm_framebuffer_funcs - framebuffer hooks
@@ -82,6 +87,9 @@ struct drm_framebuffer_funcs {
* for more information as all the semantics and arguments have a one to
* one mapping on this function.
*
+ * Atomic drivers should use drm_atomic_helper_dirtyfb() to implement
+ * this hook.
+ *
* RETURNS:
*
* 0 on success or a negative error code on failure.
@@ -241,30 +249,6 @@ static inline void drm_framebuffer_put(struct drm_framebuffer *fb)
}
/**
- * drm_framebuffer_reference - acquire a framebuffer reference
- * @fb: DRM framebuffer
- *
- * This is a compatibility alias for drm_framebuffer_get() and should not be
- * used by new code.
- */
-static inline void drm_framebuffer_reference(struct drm_framebuffer *fb)
-{
- drm_framebuffer_get(fb);
-}
-
-/**
- * drm_framebuffer_unreference - release a framebuffer reference
- * @fb: DRM framebuffer
- *
- * This is a compatibility alias for drm_framebuffer_put() and should not be
- * used by new code.
- */
-static inline void drm_framebuffer_unreference(struct drm_framebuffer *fb)
-{
- drm_framebuffer_put(fb);
-}
-
-/**
* drm_framebuffer_read_refcount - read the framebuffer reference count.
* @fb: framebuffer
*
diff --git a/sys/dev/pci/drm/include/drm/drm_gem.h b/sys/dev/pci/drm/include/drm/drm_gem.h
index 67997edbd51..5bc32a1d2b5 100644
--- a/sys/dev/pci/drm/include/drm/drm_gem.h
+++ b/sys/dev/pci/drm/include/drm/drm_gem.h
@@ -35,9 +35,146 @@
*/
#include <linux/kref.h>
+#include <linux/dma-resv.h>
#include <drm/drm_vma_manager.h>
+struct drm_gem_object;
+
+/**
+ * struct drm_gem_object_funcs - GEM object functions
+ */
+struct drm_gem_object_funcs {
+ /**
+ * @free:
+ *
+ * Deconstructor for drm_gem_objects.
+ *
+ * This callback is mandatory.
+ */
+ void (*free)(struct drm_gem_object *obj);
+
+ /**
+ * @open:
+ *
+ * Called upon GEM handle creation.
+ *
+ * This callback is optional.
+ */
+ int (*open)(struct drm_gem_object *obj, struct drm_file *file);
+
+ /**
+ * @close:
+ *
+ * Called upon GEM handle release.
+ *
+ * This callback is optional.
+ */
+ void (*close)(struct drm_gem_object *obj, struct drm_file *file);
+
+ /**
+ * @print_info:
+ *
+ * If driver subclasses struct &drm_gem_object, it can implement this
+ * optional hook for printing additional driver specific info.
+ *
+ * drm_printf_indent() should be used in the callback passing it the
+ * indent argument.
+ *
+ * This callback is called from drm_gem_print_info().
+ *
+ * This callback is optional.
+ */
+ void (*print_info)(struct drm_printer *p, unsigned int indent,
+ const struct drm_gem_object *obj);
+
+ /**
+ * @export:
+ *
+ * Export backing buffer as a &dma_buf.
+ * If this is not set drm_gem_prime_export() is used.
+ *
+ * This callback is optional.
+ */
+ struct dma_buf *(*export)(struct drm_gem_object *obj, int flags);
+
+ /**
+ * @pin:
+ *
+ * Pin backing buffer in memory. Used by the drm_gem_map_attach() helper.
+ *
+ * This callback is optional.
+ */
+ int (*pin)(struct drm_gem_object *obj);
+
+ /**
+ * @unpin:
+ *
+ * Unpin backing buffer. Used by the drm_gem_map_detach() helper.
+ *
+ * This callback is optional.
+ */
+ void (*unpin)(struct drm_gem_object *obj);
+
+ /**
+ * @get_sg_table:
+ *
+ * Returns a Scatter-Gather table representation of the buffer.
+ * Used when exporting a buffer by the drm_gem_map_dma_buf() helper.
+ * Releasing is done by calling dma_unmap_sg_attrs() and sg_free_table()
+ * in drm_gem_unmap_buf(), therefore these helpers and this callback
+ * here cannot be used for sg tables pointing at driver private memory
+ * ranges.
+ *
+ * See also drm_prime_pages_to_sg().
+ */
+ struct sg_table *(*get_sg_table)(struct drm_gem_object *obj);
+
+ /**
+ * @vmap:
+ *
+ * Returns a virtual address for the buffer. Used by the
+ * drm_gem_dmabuf_vmap() helper.
+ *
+ * This callback is optional.
+ */
+ void *(*vmap)(struct drm_gem_object *obj);
+
+ /**
+ * @vunmap:
+ *
+ * Releases the the address previously returned by @vmap. Used by the
+ * drm_gem_dmabuf_vunmap() helper.
+ *
+ * This callback is optional.
+ */
+ void (*vunmap)(struct drm_gem_object *obj, void *vaddr);
+
+ /**
+ * @mmap:
+ *
+ * Handle mmap() of the gem object, setup vma accordingly.
+ *
+ * This callback is optional.
+ *
+ * The callback is used by by both drm_gem_mmap_obj() and
+ * drm_gem_prime_mmap(). When @mmap is present @vm_ops is not
+ * used, the @mmap callback must set vma->vm_ops instead.
+ */
+#ifdef __linux__
+ int (*mmap)(struct drm_gem_object *obj, struct vm_area_struct *vma);
+#endif
+
+ /**
+ * @vm_ops:
+ *
+ * Virtual memory operations used with mmap.
+ *
+ * This is optional but necessary for mmap support.
+ */
+ const struct vm_operations_struct *vm_ops;
+};
+
/**
* struct drm_gem_object - GEM buffer object
*
@@ -47,6 +184,12 @@
* Buffer objects are often abbreviated to BO.
*/
struct drm_gem_object {
+ /*
+ * This must be first as uobj is cast to ttm_buffer_object for
+ * radeon_ttm_fault() the first member of that struct is drm_gem_object
+ */
+ struct uvm_object uobj;
+
/**
* @refcount:
*
@@ -147,7 +290,35 @@ struct drm_gem_object {
*/
struct dma_buf_attachment *import_attach;
- struct uvm_object uobj;
+ /**
+ * @resv:
+ *
+ * Pointer to reservation object associated with the this GEM object.
+ *
+ * Normally (@resv == &@_resv) except for imported GEM objects.
+ */
+ struct dma_resv *resv;
+
+ /**
+ * @_resv:
+ *
+ * A reservation object for this GEM object.
+ *
+ * This is unused for imported GEM objects.
+ */
+ struct dma_resv _resv;
+
+ /**
+ * @funcs:
+ *
+ * Optional GEM object functions. If this is set, it will be used instead of the
+ * corresponding &drm_driver GEM callbacks.
+ *
+ * New drivers should use this.
+ *
+ */
+ const struct drm_gem_object_funcs *funcs;
+
SPLAY_ENTRY(drm_gem_object) entry;
struct uvm_object *uao;
};
@@ -228,56 +399,6 @@ __drm_gem_object_put(struct drm_gem_object *obj)
void drm_gem_object_put_unlocked(struct drm_gem_object *obj);
void drm_gem_object_put(struct drm_gem_object *obj);
-/**
- * drm_gem_object_reference - acquire a GEM buffer object reference
- * @obj: GEM buffer object
- *
- * This is a compatibility alias for drm_gem_object_get() and should not be
- * used by new code.
- */
-static inline void drm_gem_object_reference(struct drm_gem_object *obj)
-{
- drm_gem_object_get(obj);
-}
-
-/**
- * __drm_gem_object_unreference - raw function to release a GEM buffer object
- * reference
- * @obj: GEM buffer object
- *
- * This is a compatibility alias for __drm_gem_object_put() and should not be
- * used by new code.
- */
-static inline void __drm_gem_object_unreference(struct drm_gem_object *obj)
-{
- __drm_gem_object_put(obj);
-}
-
-/**
- * drm_gem_object_unreference_unlocked - release a GEM buffer object reference
- * @obj: GEM buffer object
- *
- * This is a compatibility alias for drm_gem_object_put_unlocked() and should
- * not be used by new code.
- */
-static inline void
-drm_gem_object_unreference_unlocked(struct drm_gem_object *obj)
-{
- drm_gem_object_put_unlocked(obj);
-}
-
-/**
- * drm_gem_object_unreference - release a GEM buffer object reference
- * @obj: GEM buffer object
- *
- * This is a compatibility alias for drm_gem_object_put() and should not be
- * used by new code.
- */
-static inline void drm_gem_object_unreference(struct drm_gem_object *obj)
-{
- drm_gem_object_put(obj);
-}
-
int drm_gem_handle_create(struct drm_file *file_priv,
struct drm_gem_object *obj,
u32 *handlep);
@@ -288,11 +409,26 @@ void drm_gem_free_mmap_offset(struct drm_gem_object *obj);
int drm_gem_create_mmap_offset(struct drm_gem_object *obj);
int drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size);
-struct page **drm_gem_get_pages(struct drm_gem_object *obj);
-void drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages,
+struct vm_page **drm_gem_get_pages(struct drm_gem_object *obj);
+void drm_gem_put_pages(struct drm_gem_object *obj, struct vm_page **pages,
bool dirty, bool accessed);
+int drm_gem_objects_lookup(struct drm_file *filp, void __user *bo_handles,
+ int count, struct drm_gem_object ***objs_out);
struct drm_gem_object *drm_gem_object_lookup(struct drm_file *filp, u32 handle);
+long drm_gem_dma_resv_wait(struct drm_file *filep, u32 handle,
+ bool wait_all, unsigned long timeout);
+int drm_gem_lock_reservations(struct drm_gem_object **objs, int count,
+ struct ww_acquire_ctx *acquire_ctx);
+void drm_gem_unlock_reservations(struct drm_gem_object **objs, int count,
+ struct ww_acquire_ctx *acquire_ctx);
+#ifdef notyet
+int drm_gem_fence_array_add(struct xarray *fence_array,
+ struct dma_fence *fence);
+int drm_gem_fence_array_add_implicit(struct xarray *fence_array,
+ struct drm_gem_object *obj,
+ bool write);
+#endif
int drm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
u32 handle, u64 *offset);
int drm_gem_dumb_destroy(struct drm_file *file,
diff --git a/sys/dev/pci/drm/include/drm/drm_gem_cma_helper.h b/sys/dev/pci/drm/include/drm/drm_gem_cma_helper.h
index b388a0d99c7..d23766028f9 100644
--- a/sys/dev/pci/drm/include/drm/drm_gem_cma_helper.h
+++ b/sys/dev/pci/drm/include/drm/drm_gem_cma_helper.h
@@ -1,6 +1,5 @@
/* Public Domain */
-#include <drm/drmP.h>
#include <drm/drm_gem.h>
void drm_gem_cma_free_object(struct drm_gem_object *);
diff --git a/sys/dev/pci/drm/include/drm/drm_gem_framebuffer_helper.h b/sys/dev/pci/drm/include/drm/drm_gem_framebuffer_helper.h
index 9670130719f..c903667925c 100644
--- a/sys/dev/pci/drm/include/drm/drm_gem_framebuffer_helper.h
+++ b/sys/dev/pci/drm/include/drm/drm_gem_framebuffer_helper.h
@@ -1,7 +1,7 @@
/* Public domain. */
-#ifndef DRM_GEM_FRAMEBUFFER_HELPER_H
-#define DRM_GEM_FRAMEBUFFER_HELPER_H
+#ifndef _DRM_GEM_FRAMEBUFFER_HELPER_H
+#define _DRM_GEM_FRAMEBUFFER_HELPER_H
void drm_gem_fb_destroy(struct drm_framebuffer *);
int drm_gem_fb_create_handle(struct drm_framebuffer *, struct drm_file *,
diff --git a/sys/dev/pci/drm/include/drm/drm_global.h b/sys/dev/pci/drm/include/drm/drm_global.h
deleted file mode 100644
index 3a830602a2e..00000000000
--- a/sys/dev/pci/drm/include/drm/drm_global.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2008-2009 VMware, Inc., Palo Alto, CA., USA
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-/*
- * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
- */
-
-#ifndef _DRM_GLOBAL_H_
-#define _DRM_GLOBAL_H_
-enum drm_global_types {
- DRM_GLOBAL_TTM_MEM = 0,
- DRM_GLOBAL_TTM_BO,
- DRM_GLOBAL_TTM_OBJECT,
- DRM_GLOBAL_NUM
-};
-
-struct drm_global_reference {
- enum drm_global_types global_type;
- size_t size;
- void *object;
- int (*init) (struct drm_global_reference *);
- void (*release) (struct drm_global_reference *);
-};
-
-void drm_global_init(void);
-void drm_global_release(void);
-int drm_global_item_ref(struct drm_global_reference *ref);
-void drm_global_item_unref(struct drm_global_reference *ref);
-
-#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_hashtab.h b/sys/dev/pci/drm/include/drm/drm_hashtab.h
index d5d00d4c27d..bb95ff011ba 100644
--- a/sys/dev/pci/drm/include/drm/drm_hashtab.h
+++ b/sys/dev/pci/drm/include/drm/drm_hashtab.h
@@ -1,4 +1,3 @@
-/* $OpenBSD: drm_hashtab.h,v 1.1 2019/04/14 10:14:52 jsg Exp $ */
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Bismack, ND. USA.
@@ -36,32 +35,31 @@
#ifndef DRM_HASHTAB_H
#define DRM_HASHTAB_H
-#include <sys/types.h>
-#include <sys/queue.h>
+#include <linux/list.h>
#define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member)
struct drm_hash_item {
- LIST_ENTRY(drm_hash_item) head;
+ struct hlist_node head;
unsigned long key;
};
struct drm_open_hash {
- LIST_HEAD(drm_hash_item_list, drm_hash_item) *table;
- uint8_t order;
+ struct hlist_head *table;
+ u8 order;
};
-extern int drm_ht_create(struct drm_open_hash *ht, unsigned int order);
-extern int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item);
-extern int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item,
- unsigned long seed, int bits, int shift,
- unsigned long add);
-extern int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, struct drm_hash_item **item);
+int drm_ht_create(struct drm_open_hash *ht, unsigned int order);
+int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item);
+int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item,
+ unsigned long seed, int bits, int shift,
+ unsigned long add);
+int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, struct drm_hash_item **item);
-extern void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key);
-extern int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key);
-extern int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item);
-extern void drm_ht_remove(struct drm_open_hash *ht);
+void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key);
+int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key);
+int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item);
+void drm_ht_remove(struct drm_open_hash *ht);
/*
* RCU-safe interface
diff --git a/sys/dev/pci/drm/include/drm/drm_hdcp.h b/sys/dev/pci/drm/include/drm/drm_hdcp.h
index 98e63d87013..c6bab4986a6 100644
--- a/sys/dev/pci/drm/include/drm/drm_hdcp.h
+++ b/sys/dev/pci/drm/include/drm/drm_hdcp.h
@@ -9,8 +9,11 @@
#ifndef _DRM_HDCP_H_INCLUDED_
#define _DRM_HDCP_H_INCLUDED_
+#include <linux/types.h>
+
/* Period of hdcp checks (to ensure we're still authenticated) */
#define DRM_HDCP_CHECK_PERIOD_MS (128 * 16)
+#define DRM_HDCP2_CHECK_PERIOD_MS 500
/* Shared lengths/masks between HDMI/DVI/DisplayPort */
#define DRM_HDCP_AN_LEN 8
@@ -38,4 +41,262 @@
#define DRM_HDCP_DDC_BSTATUS 0x41
#define DRM_HDCP_DDC_KSV_FIFO 0x43
+#define DRM_HDCP_1_4_SRM_ID 0x8
+#define DRM_HDCP_1_4_VRL_LENGTH_SIZE 3
+#define DRM_HDCP_1_4_DCP_SIG_SIZE 40
+
+/* Protocol message definition for HDCP2.2 specification */
+/*
+ * Protected content streams are classified into 2 types:
+ * - Type0: Can be transmitted with HDCP 1.4+
+ * - Type1: Can be transmitted with HDCP 2.2+
+ */
+#define HDCP_STREAM_TYPE0 0x00
+#define HDCP_STREAM_TYPE1 0x01
+
+/* HDCP2.2 Msg IDs */
+#define HDCP_2_2_NULL_MSG 1
+#define HDCP_2_2_AKE_INIT 2
+#define HDCP_2_2_AKE_SEND_CERT 3
+#define HDCP_2_2_AKE_NO_STORED_KM 4
+#define HDCP_2_2_AKE_STORED_KM 5
+#define HDCP_2_2_AKE_SEND_HPRIME 7
+#define HDCP_2_2_AKE_SEND_PAIRING_INFO 8
+#define HDCP_2_2_LC_INIT 9
+#define HDCP_2_2_LC_SEND_LPRIME 10
+#define HDCP_2_2_SKE_SEND_EKS 11
+#define HDCP_2_2_REP_SEND_RECVID_LIST 12
+#define HDCP_2_2_REP_SEND_ACK 15
+#define HDCP_2_2_REP_STREAM_MANAGE 16
+#define HDCP_2_2_REP_STREAM_READY 17
+
+#define HDCP_2_2_RTX_LEN 8
+#define HDCP_2_2_RRX_LEN 8
+
+#define HDCP_2_2_K_PUB_RX_MOD_N_LEN 128
+#define HDCP_2_2_K_PUB_RX_EXP_E_LEN 3
+#define HDCP_2_2_K_PUB_RX_LEN (HDCP_2_2_K_PUB_RX_MOD_N_LEN + \
+ HDCP_2_2_K_PUB_RX_EXP_E_LEN)
+
+#define HDCP_2_2_DCP_LLC_SIG_LEN 384
+
+#define HDCP_2_2_E_KPUB_KM_LEN 128
+#define HDCP_2_2_E_KH_KM_M_LEN (16 + 16)
+#define HDCP_2_2_H_PRIME_LEN 32
+#define HDCP_2_2_E_KH_KM_LEN 16
+#define HDCP_2_2_RN_LEN 8
+#define HDCP_2_2_L_PRIME_LEN 32
+#define HDCP_2_2_E_DKEY_KS_LEN 16
+#define HDCP_2_2_RIV_LEN 8
+#define HDCP_2_2_SEQ_NUM_LEN 3
+#define HDCP_2_2_V_PRIME_HALF_LEN (HDCP_2_2_L_PRIME_LEN / 2)
+#define HDCP_2_2_RECEIVER_ID_LEN DRM_HDCP_KSV_LEN
+#define HDCP_2_2_MAX_DEVICE_COUNT 31
+#define HDCP_2_2_RECEIVER_IDS_MAX_LEN (HDCP_2_2_RECEIVER_ID_LEN * \
+ HDCP_2_2_MAX_DEVICE_COUNT)
+#define HDCP_2_2_MPRIME_LEN 32
+
+/* Following Macros take a byte at a time for bit(s) masking */
+/*
+ * TODO: This has to be changed for DP MST, as multiple stream on
+ * same port is possible.
+ * For HDCP2.2 on HDMI and DP SST this value is always 1.
+ */
+#define HDCP_2_2_MAX_CONTENT_STREAMS_CNT 1
+#define HDCP_2_2_TXCAP_MASK_LEN 2
+#define HDCP_2_2_RXCAPS_LEN 3
+#define HDCP_2_2_RX_REPEATER(x) ((x) & BIT(0))
+#define HDCP_2_2_DP_HDCP_CAPABLE(x) ((x) & BIT(1))
+#define HDCP_2_2_RXINFO_LEN 2
+
+/* HDCP1.x compliant device in downstream */
+#define HDCP_2_2_HDCP1_DEVICE_CONNECTED(x) ((x) & BIT(0))
+
+/* HDCP2.0 Compliant repeater in downstream */
+#define HDCP_2_2_HDCP_2_0_REP_CONNECTED(x) ((x) & BIT(1))
+#define HDCP_2_2_MAX_CASCADE_EXCEEDED(x) ((x) & BIT(2))
+#define HDCP_2_2_MAX_DEVS_EXCEEDED(x) ((x) & BIT(3))
+#define HDCP_2_2_DEV_COUNT_LO(x) (((x) & (0xF << 4)) >> 4)
+#define HDCP_2_2_DEV_COUNT_HI(x) ((x) & BIT(0))
+#define HDCP_2_2_DEPTH(x) (((x) & (0x7 << 1)) >> 1)
+
+struct hdcp2_cert_rx {
+ u8 receiver_id[HDCP_2_2_RECEIVER_ID_LEN];
+ u8 kpub_rx[HDCP_2_2_K_PUB_RX_LEN];
+ u8 reserved[2];
+ u8 dcp_signature[HDCP_2_2_DCP_LLC_SIG_LEN];
+} __packed;
+
+struct hdcp2_streamid_type {
+ u8 stream_id;
+ u8 stream_type;
+} __packed;
+
+/*
+ * The TxCaps field specified in the HDCP HDMI, DP specs
+ * This field is big endian as specified in the errata.
+ */
+struct hdcp2_tx_caps {
+ /* Transmitter must set this to 0x2 */
+ u8 version;
+
+ /* Reserved for HDCP and DP Spec. Read as Zero */
+ u8 tx_cap_mask[HDCP_2_2_TXCAP_MASK_LEN];
+} __packed;
+
+/* Main structures for HDCP2.2 protocol communication */
+struct hdcp2_ake_init {
+ u8 msg_id;
+ u8 r_tx[HDCP_2_2_RTX_LEN];
+ struct hdcp2_tx_caps tx_caps;
+} __packed;
+
+struct hdcp2_ake_send_cert {
+ u8 msg_id;
+ struct hdcp2_cert_rx cert_rx;
+ u8 r_rx[HDCP_2_2_RRX_LEN];
+ u8 rx_caps[HDCP_2_2_RXCAPS_LEN];
+} __packed;
+
+struct hdcp2_ake_no_stored_km {
+ u8 msg_id;
+ u8 e_kpub_km[HDCP_2_2_E_KPUB_KM_LEN];
+} __packed;
+
+struct hdcp2_ake_stored_km {
+ u8 msg_id;
+ u8 e_kh_km_m[HDCP_2_2_E_KH_KM_M_LEN];
+} __packed;
+
+struct hdcp2_ake_send_hprime {
+ u8 msg_id;
+ u8 h_prime[HDCP_2_2_H_PRIME_LEN];
+} __packed;
+
+struct hdcp2_ake_send_pairing_info {
+ u8 msg_id;
+ u8 e_kh_km[HDCP_2_2_E_KH_KM_LEN];
+} __packed;
+
+struct hdcp2_lc_init {
+ u8 msg_id;
+ u8 r_n[HDCP_2_2_RN_LEN];
+} __packed;
+
+struct hdcp2_lc_send_lprime {
+ u8 msg_id;
+ u8 l_prime[HDCP_2_2_L_PRIME_LEN];
+} __packed;
+
+struct hdcp2_ske_send_eks {
+ u8 msg_id;
+ u8 e_dkey_ks[HDCP_2_2_E_DKEY_KS_LEN];
+ u8 riv[HDCP_2_2_RIV_LEN];
+} __packed;
+
+struct hdcp2_rep_send_receiverid_list {
+ u8 msg_id;
+ u8 rx_info[HDCP_2_2_RXINFO_LEN];
+ u8 seq_num_v[HDCP_2_2_SEQ_NUM_LEN];
+ u8 v_prime[HDCP_2_2_V_PRIME_HALF_LEN];
+ u8 receiver_ids[HDCP_2_2_RECEIVER_IDS_MAX_LEN];
+} __packed;
+
+struct hdcp2_rep_send_ack {
+ u8 msg_id;
+ u8 v[HDCP_2_2_V_PRIME_HALF_LEN];
+} __packed;
+
+struct hdcp2_rep_stream_manage {
+ u8 msg_id;
+ u8 seq_num_m[HDCP_2_2_SEQ_NUM_LEN];
+ __be16 k;
+ struct hdcp2_streamid_type streams[HDCP_2_2_MAX_CONTENT_STREAMS_CNT];
+} __packed;
+
+struct hdcp2_rep_stream_ready {
+ u8 msg_id;
+ u8 m_prime[HDCP_2_2_MPRIME_LEN];
+} __packed;
+
+/* HDCP2.2 TIMEOUTs in mSec */
+#define HDCP_2_2_CERT_TIMEOUT_MS 100
+#define HDCP_2_2_HPRIME_NO_PAIRED_TIMEOUT_MS 1000
+#define HDCP_2_2_HPRIME_PAIRED_TIMEOUT_MS 200
+#define HDCP_2_2_PAIRING_TIMEOUT_MS 200
+#define HDCP_2_2_HDMI_LPRIME_TIMEOUT_MS 20
+#define HDCP_2_2_DP_LPRIME_TIMEOUT_MS 7
+#define HDCP_2_2_RECVID_LIST_TIMEOUT_MS 3000
+#define HDCP_2_2_STREAM_READY_TIMEOUT_MS 100
+
+/* HDMI HDCP2.2 Register Offsets */
+#define HDCP_2_2_HDMI_REG_VER_OFFSET 0x50
+#define HDCP_2_2_HDMI_REG_WR_MSG_OFFSET 0x60
+#define HDCP_2_2_HDMI_REG_RXSTATUS_OFFSET 0x70
+#define HDCP_2_2_HDMI_REG_RD_MSG_OFFSET 0x80
+#define HDCP_2_2_HDMI_REG_DBG_OFFSET 0xC0
+
+#define HDCP_2_2_HDMI_SUPPORT_MASK BIT(2)
+#define HDCP_2_2_RX_CAPS_VERSION_VAL 0x02
+#define HDCP_2_2_SEQ_NUM_MAX 0xFFFFFF
+#define HDCP_2_2_DELAY_BEFORE_ENCRYPTION_EN 200
+
+/* Below macros take a byte at a time and mask the bit(s) */
+#define HDCP_2_2_HDMI_RXSTATUS_LEN 2
+#define HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(x) ((x) & 0x3)
+#define HDCP_2_2_HDMI_RXSTATUS_READY(x) ((x) & BIT(2))
+#define HDCP_2_2_HDMI_RXSTATUS_REAUTH_REQ(x) ((x) & BIT(3))
+
+/*
+ * Helper functions to convert 24bit big endian hdcp sequence number to
+ * host format and back
+ */
+static inline
+u32 drm_hdcp_be24_to_cpu(const u8 seq_num[HDCP_2_2_SEQ_NUM_LEN])
+{
+ return (u32)(seq_num[2] | seq_num[1] << 8 | seq_num[0] << 16);
+}
+
+static inline
+void drm_hdcp_cpu_to_be24(u8 seq_num[HDCP_2_2_SEQ_NUM_LEN], u32 val)
+{
+ seq_num[0] = val >> 16;
+ seq_num[1] = val >> 8;
+ seq_num[2] = val;
+}
+
+#define DRM_HDCP_SRM_GEN1_MAX_BYTES (5 * 1024)
+#define DRM_HDCP_1_4_SRM_ID 0x8
+#define DRM_HDCP_SRM_ID_MASK (0xF << 4)
+#define DRM_HDCP_1_4_VRL_LENGTH_SIZE 3
+#define DRM_HDCP_1_4_DCP_SIG_SIZE 40
+#define DRM_HDCP_2_SRM_ID 0x9
+#define DRM_HDCP_2_INDICATOR 0x1
+#define DRM_HDCP_2_INDICATOR_MASK 0xF
+#define DRM_HDCP_2_VRL_LENGTH_SIZE 3
+#define DRM_HDCP_2_DCP_SIG_SIZE 384
+#define DRM_HDCP_2_NO_OF_DEV_PLUS_RESERVED_SZ 4
+#define DRM_HDCP_2_KSV_COUNT_2_LSBITS(byte) (((byte) & 0xC0) >> 6)
+
+struct hdcp_srm_header {
+ u8 srm_id;
+ u8 reserved;
+ __be16 srm_version;
+ u8 srm_gen_no;
+} __packed;
+
+struct drm_device;
+struct drm_connector;
+
+int drm_hdcp_check_ksvs_revoked(struct drm_device *dev,
+ u8 *ksvs, u32 ksv_count);
+int drm_connector_attach_content_protection_property(
+ struct drm_connector *connector, bool hdcp_content_type);
+void drm_hdcp_update_content_protection(struct drm_connector *connector,
+ u64 val);
+
+/* Content Type classification for HDCP2.2 vs others */
+#define DRM_MODE_HDCP_CONTENT_TYPE0 0
+#define DRM_MODE_HDCP_CONTENT_TYPE1 1
+
#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_ioctl.h b/sys/dev/pci/drm/include/drm/drm_ioctl.h
index a9edb834cd9..ca79b07962c 100644
--- a/sys/dev/pci/drm/include/drm/drm_ioctl.h
+++ b/sys/dev/pci/drm/include/drm/drm_ioctl.h
@@ -1,8 +1,14 @@
-/*-
+/*
+ * Internal Header for the Direct Rendering Manager
+ *
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * Copyright (c) 2009-2010, Code Aurora Forum.
* All rights reserved.
*
+ * Author: Rickard E. (Rik) Faith <faith@valinux.com>
+ * Author: Gareth Hughes <gareth@valinux.com>
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
@@ -21,57 +27,159 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- *
*/
#ifndef _DRM_IOCTL_H_
#define _DRM_IOCTL_H_
+#include <linux/types.h>
+#include <linux/bitops.h>
+
+#include <asm/ioctl.h>
+
struct drm_device;
struct drm_file;
struct file;
/**
- * Ioctl function type.
+ * drm_ioctl_t - DRM ioctl function type.
+ * @dev: DRM device inode
+ * @data: private pointer of the ioctl call
+ * @file_priv: DRM file this ioctl was made on
*
- * \param inode device inode.
- * \param file_priv DRM file private pointer.
- * \param cmd command.
- * \param arg argument.
+ * This is the DRM ioctl typedef. Note that drm_ioctl() has alrady copied @data
+ * into kernel-space, and will also copy it back, depending upon the read/write
+ * settings in the ioctl command code.
*/
typedef int drm_ioctl_t(struct drm_device *dev, void *data,
struct drm_file *file_priv);
+/**
+ * drm_ioctl_compat_t - compatibility DRM ioctl function type.
+ * @filp: file pointer
+ * @cmd: ioctl command code
+ * @arg: DRM file this ioctl was made on
+ *
+ * Just a typedef to make declaring an array of compatibility handlers easier.
+ * New drivers shouldn't screw up the structure layout for their ioctl
+ * structures and hence never need this.
+ */
typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,
unsigned long arg);
-#define DRM_IOCTL_NR(n) ((n) & 0xff)
+#ifdef __linux__
+#define DRM_IOCTL_NR(n) _IOC_NR(n)
+#define DRM_MAJOR 226
+#else
+#define DRM_IOCTL_NR(n) ((n) & 0xff)
+#endif
-#define DRM_AUTH 0x1
-#define DRM_MASTER 0x2
-#define DRM_ROOT_ONLY 0x4
-#define DRM_CONTROL_ALLOW 0x8
-#define DRM_UNLOCKED 0x10
-#define DRM_RENDER_ALLOW 0x20
+/**
+ * enum drm_ioctl_flags - DRM ioctl flags
+ *
+ * Various flags that can be set in &drm_ioctl_desc.flags to control how
+ * userspace can use a given ioctl.
+ */
+enum drm_ioctl_flags {
+ /**
+ * @DRM_AUTH:
+ *
+ * This is for ioctl which are used for rendering, and require that the
+ * file descriptor is either for a render node, or if it's a
+ * legacy/primary node, then it must be authenticated.
+ */
+ DRM_AUTH = BIT(0),
+ /**
+ * @DRM_MASTER:
+ *
+ * This must be set for any ioctl which can change the modeset or
+ * display state. Userspace must call the ioctl through a primary node,
+ * while it is the active master.
+ *
+ * Note that read-only modeset ioctl can also be called by
+ * unauthenticated clients, or when a master is not the currently active
+ * one.
+ */
+ DRM_MASTER = BIT(1),
+ /**
+ * @DRM_ROOT_ONLY:
+ *
+ * Anything that could potentially wreak a master file descriptor needs
+ * to have this flag set. Current that's only for the SETMASTER and
+ * DROPMASTER ioctl, which e.g. logind can call to force a non-behaving
+ * master (display compositor) into compliance.
+ *
+ * This is equivalent to callers with the SYSADMIN capability.
+ */
+ DRM_ROOT_ONLY = BIT(2),
+ /**
+ * @DRM_UNLOCKED:
+ *
+ * Whether &drm_ioctl_desc.func should be called with the DRM BKL held
+ * or not. Enforced as the default for all modern drivers, hence there
+ * should never be a need to set this flag.
+ *
+ * Do not use anywhere else than for the VBLANK_WAIT IOCTL, which is the
+ * only legacy IOCTL which needs this.
+ */
+ DRM_UNLOCKED = BIT(4),
+ /**
+ * @DRM_RENDER_ALLOW:
+ *
+ * This is used for all ioctl needed for rendering only, for drivers
+ * which support render nodes. This should be all new render drivers,
+ * and hence it should be always set for any ioctl with DRM_AUTH set.
+ * Note though that read-only query ioctl might have this set, but have
+ * not set DRM_AUTH because they do not require authentication.
+ */
+ DRM_RENDER_ALLOW = BIT(5),
+};
+/**
+ * struct drm_ioctl_desc - DRM driver ioctl entry
+ * @cmd: ioctl command number, without flags
+ * @flags: a bitmask of &enum drm_ioctl_flags
+ * @func: handler for this ioctl
+ * @name: user-readable name for debug output
+ *
+ * For convenience it's easier to create these using the DRM_IOCTL_DEF_DRV()
+ * macro.
+ */
struct drm_ioctl_desc {
unsigned int cmd;
- int flags;
+ enum drm_ioctl_flags flags;
drm_ioctl_t *func;
- unsigned int cmd_drv;
+ const char *name;
};
/**
- * Creates a driver or general drm_ioctl_desc array entry for the given
- * ioctl, for use by drm_ioctl().
+ * DRM_IOCTL_DEF_DRV() - helper macro to fill out a &struct drm_ioctl_desc
+ * @ioctl: ioctl command suffix
+ * @_func: handler for the ioctl
+ * @_flags: a bitmask of &enum drm_ioctl_flags
+ *
+ * Small helper macro to create a &struct drm_ioctl_desc entry. The ioctl
+ * command number is constructed by prepending ``DRM_IOCTL\_`` and passing that
+ * to DRM_IOCTL_NR().
*/
+#define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags) \
+ [DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = { \
+ .cmd = DRM_IOCTL_##ioctl, \
+ .func = _func, \
+ .flags = _flags, \
+ .name = #ioctl \
+ }
-#define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags) \
- [DRM_IOCTL_NR(DRM_##ioctl)] = {.cmd = DRM_##ioctl, .func = _func, .flags = _flags, .cmd_drv = DRM_IOCTL_##ioctl}
+int drm_ioctl_permit(u32 flags, struct drm_file *file_priv);
+long drm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+long drm_ioctl_kernel(struct file *, drm_ioctl_t, void *, u32);
+#ifdef CONFIG_COMPAT
+long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+#else
+/* Let drm_compat_ioctl be assigned to .compat_ioctl unconditionally */
+#define drm_compat_ioctl NULL
+#endif
+bool drm_ioctl_flags(unsigned int nr, unsigned int *flags);
int drm_noop(struct drm_device *dev, void *data,
struct drm_file *file_priv);
diff --git a/sys/dev/pci/drm/include/drm/drm_lease.h b/sys/dev/pci/drm/include/drm/drm_lease.h
index 285c3010133..c4707753f4e 100644
--- a/sys/dev/pci/drm/include/drm/drm_lease.h
+++ b/sys/dev/pci/drm/include/drm/drm_lease.h
@@ -1,9 +1,21 @@
/* Public domain. */
-#ifndef DRM_LEASE_H
-#define DRM_LEASE_H
+#ifndef _DRM_LEASE_H
+#define _DRM_LEASE_H
+
+struct drm_master;
#define drm_lease_held(f, id) (true)
#define drm_lease_filter_crtcs(f, in) (in)
+static inline void
+drm_lease_revoke(struct drm_master *m)
+{
+}
+
+static inline void
+drm_lease_destroy(struct drm_master *m)
+{
+}
+
#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_legacy.h b/sys/dev/pci/drm/include/drm/drm_legacy.h
new file mode 100644
index 00000000000..0937169deed
--- /dev/null
+++ b/sys/dev/pci/drm/include/drm/drm_legacy.h
@@ -0,0 +1,235 @@
+#ifndef __DRM_DRM_LEGACY_H__
+#define __DRM_DRM_LEGACY_H__
+/*
+ * Legacy driver interfaces for the Direct Rendering Manager
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * Copyright (c) 2009-2010, Code Aurora Forum.
+ * All rights reserved.
+ * Copyright © 2014 Intel Corporation
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ *
+ * Author: Rickard E. (Rik) Faith <faith@valinux.com>
+ * Author: Gareth Hughes <gareth@valinux.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <drm/drm.h>
+#include <drm/drm_auth.h>
+#include <drm/drm_hashtab.h>
+
+struct drm_device;
+struct drm_driver;
+struct file;
+struct pci_driver;
+
+/*
+ * Legacy Support for palateontologic DRM drivers
+ *
+ * If you add a new driver and it uses any of these functions or structures,
+ * you're doing it terribly wrong.
+ */
+
+/**
+ * DMA buffer.
+ */
+struct drm_buf {
+ int idx; /**< Index into master buflist */
+ int total; /**< Buffer size */
+ int order; /**< log-base-2(total) */
+ int used; /**< Amount of buffer in use (for DMA) */
+ unsigned long offset; /**< Byte offset (used internally) */
+ void *address; /**< Address of buffer */
+ unsigned long bus_address; /**< Bus address of buffer */
+ struct drm_buf *next; /**< Kernel-only: used for free list */
+ __volatile__ int waiting; /**< On kernel DMA queue */
+ __volatile__ int pending; /**< On hardware DMA queue */
+ struct drm_file *file_priv; /**< Private of holding file descr */
+ int context; /**< Kernel queue for this buffer */
+ int while_locked; /**< Dispatch this buffer while locked */
+ enum {
+ DRM_LIST_NONE = 0,
+ DRM_LIST_FREE = 1,
+ DRM_LIST_WAIT = 2,
+ DRM_LIST_PEND = 3,
+ DRM_LIST_PRIO = 4,
+ DRM_LIST_RECLAIM = 5
+ } list; /**< Which list we're on */
+
+ int dev_priv_size; /**< Size of buffer private storage */
+ void *dev_private; /**< Per-buffer private storage */
+};
+
+struct drm_dmamem {
+ bus_dmamap_t map;
+ caddr_t kva;
+ bus_size_t size;
+ int nsegs;
+ bus_dma_segment_t segs[1];
+};
+
+typedef struct drm_dma_handle {
+ struct drm_dmamem *mem;
+ dma_addr_t busaddr;
+ void *vaddr;
+ size_t size;
+} drm_dma_handle_t;
+
+struct drm_dmamem *drm_dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t,
+ int, bus_size_t, int, int);
+void drm_dmamem_free(bus_dma_tag_t, struct drm_dmamem *);
+
+/**
+ * Buffer entry. There is one of this for each buffer size order.
+ */
+struct drm_buf_entry {
+ int buf_size; /**< size */
+ int buf_count; /**< number of buffers */
+ struct drm_buf *buflist; /**< buffer list */
+ int seg_count;
+ int page_order;
+ struct drm_dma_handle **seglist;
+
+ int low_mark; /**< Low water mark */
+ int high_mark; /**< High water mark */
+};
+
+/**
+ * DMA data.
+ */
+struct drm_device_dma {
+
+ struct drm_buf_entry bufs[DRM_MAX_ORDER + 1]; /**< buffers, grouped by their size order */
+ int buf_count; /**< total number of buffers */
+ struct drm_buf **buflist; /**< Vector of pointers into drm_device_dma::bufs */
+ int seg_count;
+ int page_count; /**< number of pages */
+ unsigned long *pagelist; /**< page list */
+ unsigned long byte_count;
+ enum {
+ _DRM_DMA_USE_AGP = 0x01,
+ _DRM_DMA_USE_SG = 0x02,
+ _DRM_DMA_USE_FB = 0x04,
+ _DRM_DMA_USE_PCI_RO = 0x08
+ } flags;
+
+};
+
+/**
+ * Scatter-gather memory.
+ */
+struct drm_sg_mem {
+ unsigned long handle;
+ void *virtual;
+ int pages;
+ struct vm_page **pagelist;
+ dma_addr_t *busaddr;
+};
+
+/**
+ * Kernel side of a mapping
+ */
+struct drm_local_map {
+ dma_addr_t offset; /**< Requested physical address (0 for SAREA)*/
+ unsigned long size; /**< Requested physical size (bytes) */
+ enum drm_map_type type; /**< Type of memory to map */
+ enum drm_map_flags flags; /**< Flags */
+ void *handle; /**< User-space: "Handle" to pass to mmap() */
+ /**< Kernel-space: kernel-virtual address */
+ int mtrr; /**< MTRR slot used */
+};
+
+typedef struct drm_local_map drm_local_map_t;
+
+/**
+ * Mappings list
+ */
+struct drm_map_list {
+ struct list_head head; /**< list head */
+ struct drm_hash_item hash;
+ struct drm_local_map *map; /**< mapping */
+ uint64_t user_token;
+ struct drm_master *master;
+};
+
+int drm_legacy_addmap(struct drm_device *d, resource_size_t offset,
+ unsigned int size, enum drm_map_type type,
+ enum drm_map_flags flags, struct drm_local_map **map_p);
+struct drm_local_map *drm_legacy_findmap(struct drm_device *dev, unsigned int token);
+void drm_legacy_rmmap(struct drm_device *d, struct drm_local_map *map);
+int drm_legacy_rmmap_locked(struct drm_device *d, struct drm_local_map *map);
+struct drm_local_map *drm_legacy_getsarea(struct drm_device *dev);
+#ifdef __linux__
+int drm_legacy_mmap(struct file *filp, struct vm_area_struct *vma);
+#endif
+
+int drm_legacy_addbufs_agp(struct drm_device *d, struct drm_buf_desc *req);
+int drm_legacy_addbufs_pci(struct drm_device *d, struct drm_buf_desc *req);
+
+/**
+ * Test that the hardware lock is held by the caller, returning otherwise.
+ *
+ * \param dev DRM device.
+ * \param filp file pointer of the caller.
+ */
+#define LOCK_TEST_WITH_RETURN( dev, _file_priv ) \
+do { \
+ if (!_DRM_LOCK_IS_HELD(_file_priv->master->lock.hw_lock->lock) || \
+ _file_priv->master->lock.file_priv != _file_priv) { \
+ DRM_ERROR( "%s called without lock held, held %d owner %p %p\n",\
+ __func__, _DRM_LOCK_IS_HELD(_file_priv->master->lock.hw_lock->lock),\
+ _file_priv->master->lock.file_priv, _file_priv); \
+ return -EINVAL; \
+ } \
+} while (0)
+
+void drm_legacy_idlelock_take(struct drm_lock_data *lock);
+void drm_legacy_idlelock_release(struct drm_lock_data *lock);
+
+/* drm_pci.c */
+
+#ifdef CONFIG_PCI
+
+int drm_legacy_pci_init(struct drm_driver *driver, struct pci_driver *pdriver);
+void drm_legacy_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver);
+
+#else
+
+static inline int drm_legacy_pci_init(struct drm_driver *driver,
+ struct pci_driver *pdriver)
+{
+ return -EINVAL;
+}
+
+static inline void drm_legacy_pci_exit(struct drm_driver *driver,
+ struct pci_driver *pdriver)
+{
+}
+
+#endif
+
+/* drm_memory.c */
+void drm_legacy_ioremap(struct drm_local_map *map, struct drm_device *dev);
+void drm_legacy_ioremap_wc(struct drm_local_map *map, struct drm_device *dev);
+void drm_legacy_ioremapfree(struct drm_local_map *map, struct drm_device *dev);
+
+#endif /* __DRM_DRM_LEGACY_H__ */
diff --git a/sys/dev/pci/drm/include/drm/drm_mipi_dsi.h b/sys/dev/pci/drm/include/drm/drm_mipi_dsi.h
index 79f41d0060f..47f34f5dccd 100644
--- a/sys/dev/pci/drm/include/drm/drm_mipi_dsi.h
+++ b/sys/dev/pci/drm/include/drm/drm_mipi_dsi.h
@@ -1,7 +1,7 @@
/* Public domain. */
-#ifndef _DEV_PCI_DRM_DRM_MIPI_DSI_H_
-#define _DEV_PCI_DRM_DRM_MIPI_DSI_H_
+#ifndef _DRM_MIPI_DSI_H_
+#define _DRM_MIPI_DSI_H_
#include <sys/types.h>
#include <linux/errno.h>
@@ -10,6 +10,7 @@
struct mipi_dsi_host;
struct mipi_dsi_device;
struct mipi_dsi_msg;
+struct drm_dsc_picture_parameter_set;
struct mipi_dsi_host_ops {
int (*attach)(struct mipi_dsi_host *, struct mipi_dsi_device *);
@@ -33,7 +34,7 @@ struct mipi_dsi_msg {
uint8_t channel;
uint16_t flags;
#define MIPI_DSI_MSG_USE_LPM (1 << 0)
- const uint8_t *tx_buf;
+ const void *tx_buf;
size_t tx_len;
uint8_t *rx_buf;
size_t rx_len;
@@ -65,6 +66,12 @@ ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *, const void *,
size_t);
ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *, u8, void *, size_t);
ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *, u8, const void *, size_t);
+int mipi_dsi_dcs_nop(struct mipi_dsi_device *);
+int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *, u16);
+bool mipi_dsi_packet_format_is_long(u8);
+ssize_t mipi_dsi_compression_mode(struct mipi_dsi_device *, bool);
+ssize_t mipi_dsi_picture_parameter_set(struct mipi_dsi_device *,
+ const struct drm_dsc_picture_parameter_set *);
static inline int
mipi_dsi_pixel_format_to_bpp(enum mipi_dsi_pixel_format fmt)
diff --git a/sys/dev/pci/drm/include/drm/drm_mode_config.h b/sys/dev/pci/drm/include/drm/drm_mode_config.h
index 453fcc2c9c0..d22c3f0ac67 100644
--- a/sys/dev/pci/drm/include/drm/drm_mode_config.h
+++ b/sys/dev/pci/drm/include/drm/drm_mode_config.h
@@ -52,6 +52,12 @@ struct drm_mode_config_funcs {
* requested metadata, but most of that is left to the driver. See
* &struct drm_mode_fb_cmd2 for details.
*
+ * To validate the pixel format and modifier drivers can use
+ * drm_any_plane_has_format() to make sure at least one plane supports
+ * the requested values. Note that the driver must first determine the
+ * actual modifier used if the request doesn't have it specified,
+ * ie. when (@mode_cmd->flags & DRM_MODE_FB_MODIFIERS) == 0.
+ *
* If the parameters are deemed valid and the backing storage objects in
* the underlying memory manager all exist, then the driver allocates
* a new &drm_framebuffer structure, subclassed to contain
@@ -355,7 +361,7 @@ struct drm_mode_config {
*
* This is the big scary modeset BKL which protects everything that
* isn't protect otherwise. Scope is unclear and fuzzy, try to remove
- * anything from under it's protection and move it into more well-scoped
+ * anything from under its protection and move it into more well-scoped
* locks.
*
* The one important thing this protects is the use of @acquire_ctx.
@@ -385,18 +391,18 @@ struct drm_mode_config {
/**
* @idr_mutex:
*
- * Mutex for KMS ID allocation and management. Protects both @crtc_idr
+ * Mutex for KMS ID allocation and management. Protects both @object_idr
* and @tile_idr.
*/
struct rwlock idr_mutex;
/**
- * @crtc_idr:
+ * @object_idr:
*
* Main KMS ID tracking object. Use this idr for all IDs, fb, crtc,
* connector, modes - just makes life easier to have only one.
*/
- struct idr crtc_idr;
+ struct idr object_idr;
/**
* @tile_idr:
@@ -506,6 +512,15 @@ struct drm_mode_config {
*/
struct list_head property_list;
+ /**
+ * @privobj_list:
+ *
+ * List of private objects linked with &drm_private_obj.head. This is
+ * invariant over the lifetime of a device and hence doesn't need any
+ * locks.
+ */
+ struct list_head privobj_list;
+
int min_width, min_height;
int max_width, max_height;
const struct drm_mode_config_funcs *funcs;
@@ -628,6 +643,15 @@ struct drm_mode_config {
*/
struct drm_property *prop_crtc_id;
/**
+ * @prop_fb_damage_clips: Optional plane property to mark damaged
+ * regions on the plane in framebuffer coordinates of the framebuffer
+ * attached to the plane.
+ *
+ * The layout of blob data is simply an array of &drm_mode_rect. Unlike
+ * plane src coordinates, damage clips are not in 16.16 fixed point.
+ */
+ struct drm_property *prop_fb_damage_clips;
+ /**
* @prop_active: Default atomic CRTC property to control the active
* state, which is the simplified implementation for DPMS in atomic
* drivers.
@@ -639,6 +663,11 @@ struct drm_mode_config {
* connectors must be of and active must be set to disabled, too.
*/
struct drm_property *prop_mode_id;
+ /**
+ * @prop_vrr_enabled: Default atomic CRTC property to indicate
+ * whether variable refresh rate should be enabled on the CRTC.
+ */
+ struct drm_property *prop_vrr_enabled;
/**
* @dvi_i_subconnector_property: Optional DVI-I property to
@@ -668,22 +697,22 @@ struct drm_mode_config {
struct drm_property *tv_mode_property;
/**
* @tv_left_margin_property: Optional TV property to set the left
- * margin.
+ * margin (expressed in pixels).
*/
struct drm_property *tv_left_margin_property;
/**
* @tv_right_margin_property: Optional TV property to set the right
- * margin.
+ * margin (expressed in pixels).
*/
struct drm_property *tv_right_margin_property;
/**
* @tv_top_margin_property: Optional TV property to set the right
- * margin.
+ * margin (expressed in pixels).
*/
struct drm_property *tv_top_margin_property;
/**
* @tv_bottom_margin_property: Optional TV property to set the right
- * margin.
+ * margin (expressed in pixels).
*/
struct drm_property *tv_bottom_margin_property;
/**
@@ -807,10 +836,58 @@ struct drm_mode_config {
*/
struct drm_property *writeback_out_fence_ptr_property;
+ /**
+ * @hdr_output_metadata_property: Connector property containing hdr
+ * metatada. This will be provided by userspace compositors based
+ * on HDR content
+ */
+ struct drm_property *hdr_output_metadata_property;
+
+ /**
+ * @content_protection_property: DRM ENUM property for content
+ * protection. See drm_connector_attach_content_protection_property().
+ */
+ struct drm_property *content_protection_property;
+
+ /**
+ * @hdcp_content_type_property: DRM ENUM property for type of
+ * Protected Content.
+ */
+ struct drm_property *hdcp_content_type_property;
+
/* dumb ioctl parameters */
uint32_t preferred_depth, prefer_shadow;
/**
+ * @prefer_shadow_fbdev:
+ *
+ * Hint to framebuffer emulation to prefer shadow-fb rendering.
+ */
+ bool prefer_shadow_fbdev;
+
+ /**
+ * @quirk_addfb_prefer_xbgr_30bpp:
+ *
+ * Special hack for legacy ADDFB to keep nouveau userspace happy. Should
+ * only ever be set by the nouveau kernel driver.
+ */
+ bool quirk_addfb_prefer_xbgr_30bpp;
+
+ /**
+ * @quirk_addfb_prefer_host_byte_order:
+ *
+ * When set to true drm_mode_addfb() will pick host byte order
+ * pixel_format when calling drm_mode_addfb2(). This is how
+ * drm_mode_addfb() should have worked from day one. It
+ * didn't though, so we ended up with quirks in both kernel
+ * and userspace drivers to deal with the broken behavior.
+ * Simply fixing drm_mode_addfb() unconditionally would break
+ * these drivers, so add a quirk bit here to allow drivers
+ * opt-in.
+ */
+ bool quirk_addfb_prefer_host_byte_order;
+
+ /**
* @async_page_flip: Does this device support async flips on the primary
* plane?
*/
diff --git a/sys/dev/pci/drm/include/drm/drm_modes.h b/sys/dev/pci/drm/include/drm/drm_modes.h
index 8b3d17fa214..320f8112a0f 100644
--- a/sys/dev/pci/drm/include/drm/drm_modes.h
+++ b/sys/dev/pci/drm/include/drm/drm_modes.h
@@ -27,8 +27,6 @@
#ifndef __DRM_MODES_H__
#define __DRM_MODES_H__
-struct videomode;
-
#include <linux/hdmi.h>
#include <drm/drm_mode_object.h>
@@ -50,7 +48,7 @@ struct videomode;
* @MODE_HSYNC: hsync out of range
* @MODE_VSYNC: vsync out of range
* @MODE_H_ILLEGAL: mode has illegal horizontal timings
- * @MODE_V_ILLEGAL: mode has illegal horizontal timings
+ * @MODE_V_ILLEGAL: mode has illegal vertical timings
* @MODE_BAD_WIDTH: requires an unsupported linepitch
* @MODE_NOMODE: no mode with a matching name
* @MODE_NO_INTERLACE: interlaced mode not supported
@@ -138,8 +136,24 @@ enum drm_mode_status {
.hdisplay = (hd), .hsync_start = (hss), .hsync_end = (hse), \
.htotal = (ht), .hskew = (hsk), .vdisplay = (vd), \
.vsync_start = (vss), .vsync_end = (vse), .vtotal = (vt), \
- .vscan = (vs), .flags = (f), \
- .base.type = DRM_MODE_OBJECT_MODE
+ .vscan = (vs), .flags = (f)
+
+/**
+ * DRM_SIMPLE_MODE - Simple display mode
+ * @hd: Horizontal resolution, width
+ * @vd: Vertical resolution, height
+ * @hd_mm: Display width in millimeters
+ * @vd_mm: Display height in millimeters
+ *
+ * This macro initializes a &drm_display_mode that only contains info about
+ * resolution and physical size.
+ */
+#define DRM_SIMPLE_MODE(hd, vd, hd_mm, vd_mm) \
+ .type = DRM_MODE_TYPE_DRIVER, .clock = 1 /* pass validation */, \
+ .hdisplay = (hd), .hsync_start = (hd), .hsync_end = (hd), \
+ .htotal = (hd), .vdisplay = (vd), .vsync_start = (vd), \
+ .vsync_end = (vd), .vtotal = (vd), .width_mm = (hd_mm), \
+ .height_mm = (vd_mm)
#define CRTC_INTERLACE_HALVE_V (1 << 0) /* halve V values for interlacing */
#define CRTC_STEREO_DOUBLE (1 << 1) /* adjust timings for stereo modes */
@@ -216,20 +230,6 @@ struct drm_display_mode {
struct list_head head;
/**
- * @base:
- *
- * A display mode is a normal modeset object, possibly including public
- * userspace id.
- *
- * FIXME:
- *
- * This can probably be removed since the entire concept of userspace
- * managing modes explicitly has never landed in upstream kernel mode
- * setting support.
- */
- struct drm_mode_object base;
-
- /**
* @name:
*
* Human-readable name of the mode, filled out with drm_mode_set_name().
@@ -371,20 +371,13 @@ struct drm_display_mode {
int crtc_vtotal;
/**
- * @private:
+ * @private_flags:
*
- * Pointer for driver private data. This can only be used for mode
+ * Driver private flags. private_flags can only be used for mode
* objects passed to drivers in modeset operations. It shouldn't be used
* by atomic drivers since they can store any additional data by
* subclassing state structures.
*/
- int *private;
-
- /**
- * @private_flags:
- *
- * Similar to @private, but just an integer.
- */
int private_flags;
/**
@@ -431,14 +424,14 @@ struct drm_display_mode {
/**
* DRM_MODE_FMT - printf string for &struct drm_display_mode
*/
-#define DRM_MODE_FMT "%d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x"
+#define DRM_MODE_FMT "\"%s\": %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x"
/**
* DRM_MODE_ARG - printf arguments for &struct drm_display_mode
* @m: display mode
*/
#define DRM_MODE_ARG(m) \
- (m)->base.id, (m)->name, (m)->vrefresh, (m)->clock, \
+ (m)->name, (m)->vrefresh, (m)->clock, \
(m)->hdisplay, (m)->hsync_start, (m)->hsync_end, (m)->htotal, \
(m)->vdisplay, (m)->vsync_start, (m)->vsync_end, (m)->vtotal, \
(m)->type, (m)->flags
@@ -537,7 +530,7 @@ void drm_connector_list_update(struct drm_connector *connector);
/* parsing cmdline modes */
bool
drm_mode_parse_command_line_for_connector(const char *mode_option,
- struct drm_connector *connector,
+ const struct drm_connector *connector,
struct drm_cmdline_mode *mode);
struct drm_display_mode *
drm_mode_create_from_cmdline_mode(struct drm_device *dev,
diff --git a/sys/dev/pci/drm/include/drm/drm_modeset_helper.h b/sys/dev/pci/drm/include/drm/drm_modeset_helper.h
index efa337f0312..995fd981cab 100644
--- a/sys/dev/pci/drm/include/drm/drm_modeset_helper.h
+++ b/sys/dev/pci/drm/include/drm/drm_modeset_helper.h
@@ -23,7 +23,11 @@
#ifndef __DRM_KMS_HELPER_H__
#define __DRM_KMS_HELPER_H__
-#include <drm/drmP.h>
+struct drm_crtc;
+struct drm_crtc_funcs;
+struct drm_device;
+struct drm_framebuffer;
+struct drm_mode_fb_cmd2;
void drm_helper_move_panel_connectors_to_head(struct drm_device *);
diff --git a/sys/dev/pci/drm/include/drm/drm_modeset_helper_vtables.h b/sys/dev/pci/drm/include/drm/drm_modeset_helper_vtables.h
index 0eb3372d031..7c20b1c8b6a 100644
--- a/sys/dev/pci/drm/include/drm/drm_modeset_helper_vtables.h
+++ b/sys/dev/pci/drm/include/drm/drm_modeset_helper_vtables.h
@@ -49,6 +49,8 @@
*/
enum mode_set_atomic;
+struct drm_writeback_connector;
+struct drm_writeback_job;
/**
* struct drm_crtc_helper_funcs - helper operations for CRTCs
@@ -418,6 +420,8 @@ struct drm_crtc_helper_funcs {
* Drivers can use the @old_crtc_state input parameter if the operations
* needed to enable the CRTC don't depend solely on the new state but
* also on the transition between the old state and the new state.
+ *
+ * This function is optional.
*/
void (*atomic_enable)(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state);
@@ -441,9 +445,58 @@ struct drm_crtc_helper_funcs {
* parameter @old_crtc_state which could be used to access the old
* state. Atomic drivers should consider to use this one instead
* of @disable.
+ *
+ * This function is optional.
*/
void (*atomic_disable)(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state);
+
+ /**
+ * @get_scanout_position:
+ *
+ * Called by vblank timestamping code.
+ *
+ * Returns the current display scanout position from a CRTC and an
+ * optional accurate ktime_get() timestamp of when the position was
+ * measured. Note that this is a helper callback which is only used
+ * if a driver uses drm_crtc_vblank_helper_get_vblank_timestamp()
+ * for the @drm_crtc_funcs.get_vblank_timestamp callback.
+ *
+ * Parameters:
+ *
+ * crtc:
+ * The CRTC.
+ * in_vblank_irq:
+ * True when called from drm_crtc_handle_vblank(). Some drivers
+ * need to apply some workarounds for gpu-specific vblank irq
+ * quirks if the flag is set.
+ * vpos:
+ * Target location for current vertical scanout position.
+ * hpos:
+ * Target location for current horizontal scanout position.
+ * stime:
+ * Target location for timestamp taken immediately before
+ * scanout position query. Can be NULL to skip timestamp.
+ * etime:
+ * Target location for timestamp taken immediately after
+ * scanout position query. Can be NULL to skip timestamp.
+ * mode:
+ * Current display timings.
+ *
+ * Returns vpos as a positive number while in active scanout area.
+ * Returns vpos as a negative number inside vblank, counting the number
+ * of scanlines to go until end of vblank, e.g., -1 means "one scanline
+ * until start of active scanout / end of vblank."
+ *
+ * Returns:
+ *
+ * True on success, false if a reliable scanout position counter could
+ * not be read out.
+ */
+ bool (*get_scanout_position)(struct drm_crtc *crtc,
+ bool in_vblank_irq, int *vpos, int *hpos,
+ ktime_t *stime, ktime_t *etime,
+ const struct drm_display_mode *mode);
};
/**
@@ -640,22 +693,6 @@ struct drm_encoder_helper_funcs {
struct drm_connector_state *conn_state);
/**
- * @get_crtc:
- *
- * This callback is used by the legacy CRTC helpers to work around
- * deficiencies in its own book-keeping.
- *
- * Do not use, use atomic helpers instead, which get the book keeping
- * right.
- *
- * FIXME:
- *
- * Currently only nouveau is using this, and as soon as nouveau is
- * atomic we can ditch this hook.
- */
- struct drm_crtc *(*get_crtc)(struct drm_encoder *encoder);
-
- /**
* @detect:
*
* This callback can be used by drivers who want to do detection on the
@@ -674,6 +711,52 @@ struct drm_encoder_helper_funcs {
struct drm_connector *connector);
/**
+ * @atomic_disable:
+ *
+ * This callback should be used to disable the encoder. With the atomic
+ * drivers it is called before this encoder's CRTC has been shut off
+ * using their own &drm_crtc_helper_funcs.atomic_disable hook. If that
+ * sequence is too simple drivers can just add their own driver private
+ * encoder hooks and call them from CRTC's callback by looping over all
+ * encoders connected to it using for_each_encoder_on_crtc().
+ *
+ * This callback is a variant of @disable that provides the atomic state
+ * to the driver. If @atomic_disable is implemented, @disable is not
+ * called by the helpers.
+ *
+ * This hook is only used by atomic helpers. Atomic drivers don't need
+ * to implement it if there's no need to disable anything at the encoder
+ * level. To ensure that runtime PM handling (using either DPMS or the
+ * new "ACTIVE" property) works @atomic_disable must be the inverse of
+ * @atomic_enable.
+ */
+ void (*atomic_disable)(struct drm_encoder *encoder,
+ struct drm_atomic_state *state);
+
+ /**
+ * @atomic_enable:
+ *
+ * This callback should be used to enable the encoder. It is called
+ * after this encoder's CRTC has been enabled using their own
+ * &drm_crtc_helper_funcs.atomic_enable hook. If that sequence is
+ * too simple drivers can just add their own driver private encoder
+ * hooks and call them from CRTC's callback by looping over all encoders
+ * connected to it using for_each_encoder_on_crtc().
+ *
+ * This callback is a variant of @enable that provides the atomic state
+ * to the driver. If @atomic_enable is implemented, @enable is not
+ * called by the helpers.
+ *
+ * This hook is only used by atomic helpers, it is the opposite of
+ * @atomic_disable. Atomic drivers don't need to implement it if there's
+ * no need to enable anything at the encoder level. To ensure that
+ * runtime PM handling works @atomic_enable must be the inverse of
+ * @atomic_disable.
+ */
+ void (*atomic_enable)(struct drm_encoder *encoder,
+ struct drm_atomic_state *state);
+
+ /**
* @disable:
*
* This callback should be used to disable the encoder. With the atomic
@@ -689,6 +772,9 @@ struct drm_encoder_helper_funcs {
* handling (using either DPMS or the new "ACTIVE" property) works
* @disable must be the inverse of @enable for atomic drivers.
*
+ * For atomic drivers also consider @atomic_disable and save yourself
+ * from having to read the NOTE below!
+ *
* NOTE:
*
* With legacy CRTC helpers there's a big semantic difference between
@@ -713,11 +799,11 @@ struct drm_encoder_helper_funcs {
* hooks and call them from CRTC's callback by looping over all encoders
* connected to it using for_each_encoder_on_crtc().
*
- * This hook is used only by atomic helpers, for symmetry with @disable.
- * Atomic drivers don't need to implement it if there's no need to
- * enable anything at the encoder level. To ensure that runtime PM handling
- * (using either DPMS or the new "ACTIVE" property) works
- * @enable must be the inverse of @disable for atomic drivers.
+ * This hook is only used by atomic helpers, it is the opposite of
+ * @disable. Atomic drivers don't need to implement it if there's no
+ * need to enable anything at the encoder level. To ensure that
+ * runtime PM handling (using either DPMS or the new "ACTIVE" property)
+ * works @enable must be the inverse of @disable for atomic drivers.
*/
void (*enable)(struct drm_encoder *encoder);
@@ -900,9 +986,8 @@ struct drm_connector_helper_funcs {
* @atomic_best_encoder.
*
* You can leave this function to NULL if the connector is only
- * attached to a single encoder and you are using the atomic helpers.
- * In this case, the core will call drm_atomic_helper_best_encoder()
- * for you.
+ * attached to a single encoder. In this case, the core will call
+ * drm_connector_get_single_encoder() for you.
*
* RETURNS:
*
@@ -922,7 +1007,7 @@ struct drm_connector_helper_funcs {
*
* This function is used by drm_atomic_helper_check_modeset().
* If it is not implemented, the core will fallback to @best_encoder
- * (or drm_atomic_helper_best_encoder() if @best_encoder is NULL).
+ * (or drm_connector_get_single_encoder() if @best_encoder is NULL).
*
* NOTE:
*
@@ -973,7 +1058,7 @@ struct drm_connector_helper_funcs {
* deadlock.
*/
int (*atomic_check)(struct drm_connector *connector,
- struct drm_connector_state *state);
+ struct drm_atomic_state *state);
/**
* @atomic_commit:
@@ -989,6 +1074,11 @@ struct drm_connector_helper_funcs {
*/
void (*atomic_commit)(struct drm_connector *connector,
struct drm_connector_state *state);
+
+ int (*prepare_writeback_job)(struct drm_writeback_connector *connector,
+ struct drm_writeback_job *job);
+ void (*cleanup_writeback_job)(struct drm_writeback_connector *connector,
+ struct drm_writeback_job *job);
};
/**
@@ -1013,7 +1103,7 @@ struct drm_plane_helper_funcs {
* @prepare_fb:
*
* This hook is to prepare a framebuffer for scanout by e.g. pinning
- * it's backing storage or relocating it into a contiguous block of
+ * its backing storage or relocating it into a contiguous block of
* VRAM. Other possible preparatory work includes flushing caches.
*
* This function must not block for outstanding rendering, since it is
diff --git a/sys/dev/pci/drm/include/drm/drm_modeset_lock.h b/sys/dev/pci/drm/include/drm/drm_modeset_lock.h
index a685d1bb21f..4fc9a43ac45 100644
--- a/sys/dev/pci/drm/include/drm/drm_modeset_lock.h
+++ b/sys/dev/pci/drm/include/drm/drm_modeset_lock.h
@@ -68,7 +68,7 @@ struct drm_modeset_acquire_ctx {
/**
* struct drm_modeset_lock - used for locking modeset resources.
* @mutex: resource locking
- * @head: used to hold it's place on &drm_atomi_state.locked list when
+ * @head: used to hold its place on &drm_atomi_state.locked list when
* part of an atomic update
*
* Used for locking CRTCs and other modeset resources.
@@ -114,6 +114,15 @@ static inline bool drm_modeset_is_locked(struct drm_modeset_lock *lock)
return ww_mutex_is_locked(&lock->mutex);
}
+/**
+ * drm_modeset_lock_assert_held - equivalent to lockdep_assert_held()
+ * @lock: lock to check
+ */
+static inline void drm_modeset_lock_assert_held(struct drm_modeset_lock *lock)
+{
+ lockdep_assert_held(&lock->mutex.base);
+}
+
int drm_modeset_lock(struct drm_modeset_lock *lock,
struct drm_modeset_acquire_ctx *ctx);
int __must_check drm_modeset_lock_single_interruptible(struct drm_modeset_lock *lock);
@@ -130,4 +139,63 @@ void drm_warn_on_modeset_not_all_locked(struct drm_device *dev);
int drm_modeset_lock_all_ctx(struct drm_device *dev,
struct drm_modeset_acquire_ctx *ctx);
+/**
+ * DRM_MODESET_LOCK_ALL_BEGIN - Helper to acquire modeset locks
+ * @dev: drm device
+ * @ctx: local modeset acquire context, will be dereferenced
+ * @flags: DRM_MODESET_ACQUIRE_* flags to pass to drm_modeset_acquire_init()
+ * @ret: local ret/err/etc variable to track error status
+ *
+ * Use these macros to simplify grabbing all modeset locks using a local
+ * context. This has the advantage of reducing boilerplate, but also properly
+ * checking return values where appropriate.
+ *
+ * Any code run between BEGIN and END will be holding the modeset locks.
+ *
+ * This must be paired with DRM_MODESET_LOCK_ALL_END(). We will jump back and
+ * forth between the labels on deadlock and error conditions.
+ *
+ * Drivers can acquire additional modeset locks. If any lock acquisition
+ * fails, the control flow needs to jump to DRM_MODESET_LOCK_ALL_END() with
+ * the @ret parameter containing the return value of drm_modeset_lock().
+ *
+ * Returns:
+ * The only possible value of ret immediately after DRM_MODESET_LOCK_ALL_BEGIN()
+ * is 0, so no error checking is necessary
+ */
+#define DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, flags, ret) \
+ drm_modeset_acquire_init(&ctx, flags); \
+modeset_lock_retry: \
+ ret = drm_modeset_lock_all_ctx(dev, &ctx); \
+ if (ret) \
+ goto modeset_lock_fail;
+
+/**
+ * DRM_MODESET_LOCK_ALL_END - Helper to release and cleanup modeset locks
+ * @ctx: local modeset acquire context, will be dereferenced
+ * @ret: local ret/err/etc variable to track error status
+ *
+ * The other side of DRM_MODESET_LOCK_ALL_BEGIN(). It will bounce back to BEGIN
+ * if ret is -EDEADLK.
+ *
+ * It's important that you use the same ret variable for begin and end so
+ * deadlock conditions are properly handled.
+ *
+ * Returns:
+ * ret will be untouched unless it is -EDEADLK on entry. That means that if you
+ * successfully acquire the locks, ret will be whatever your code sets it to. If
+ * there is a deadlock or other failure with acquire or backoff, ret will be set
+ * to that failure. In both of these cases the code between BEGIN/END will not
+ * be run, so the failure will reflect the inability to grab the locks.
+ */
+#define DRM_MODESET_LOCK_ALL_END(ctx, ret) \
+modeset_lock_fail: \
+ if (ret == -EDEADLK) { \
+ ret = drm_modeset_backoff(&ctx); \
+ if (!ret) \
+ goto modeset_lock_retry; \
+ } \
+ drm_modeset_drop_locks(&ctx); \
+ drm_modeset_acquire_fini(&ctx);
+
#endif /* DRM_MODESET_LOCK_H_ */
diff --git a/sys/dev/pci/drm/include/drm/drm_panel.h b/sys/dev/pci/drm/include/drm/drm_panel.h
index 675aa1e876c..6193cb555ac 100644
--- a/sys/dev/pci/drm/include/drm/drm_panel.h
+++ b/sys/dev/pci/drm/include/drm/drm_panel.h
@@ -28,6 +28,7 @@
#include <linux/errno.h>
#include <linux/list.h>
+struct backlight_device;
struct device_node;
struct drm_connector;
struct drm_device;
@@ -36,14 +37,6 @@ struct display_timing;
/**
* struct drm_panel_funcs - perform operations on a given panel
- * @disable: disable panel (turn off back light, etc.)
- * @unprepare: turn off panel
- * @prepare: turn on panel and perform set up
- * @enable: enable panel (turn on back light, etc.)
- * @get_modes: add modes to the connector that the panel is attached to and
- * return the number of modes added
- * @get_timings: copy display timings into the provided array and return
- * the number of display timings available
*
* The .prepare() function is typically called before the display controller
* starts to transmit video data. Panel drivers can use this to turn the panel
@@ -67,133 +60,134 @@ struct display_timing;
*
* To save power when no video data is transmitted, a driver can power down
* the panel. This is the job of the .unprepare() function.
+ *
+ * Backlight can be handled automatically if configured using
+ * drm_panel_of_backlight(). Then the driver does not need to implement the
+ * functionality to enable/disable backlight.
*/
struct drm_panel_funcs {
- int (*disable)(struct drm_panel *panel);
- int (*unprepare)(struct drm_panel *panel);
+ /**
+ * @prepare:
+ *
+ * Turn on panel and perform set up.
+ *
+ * This function is optional.
+ */
int (*prepare)(struct drm_panel *panel);
+
+ /**
+ * @enable:
+ *
+ * Enable panel (turn on back light, etc.).
+ *
+ * This function is optional.
+ */
int (*enable)(struct drm_panel *panel);
- int (*get_modes)(struct drm_panel *panel);
+
+ /**
+ * @disable:
+ *
+ * Disable panel (turn off back light, etc.).
+ *
+ * This function is optional.
+ */
+ int (*disable)(struct drm_panel *panel);
+
+ /**
+ * @unprepare:
+ *
+ * Turn off panel.
+ *
+ * This function is optional.
+ */
+ int (*unprepare)(struct drm_panel *panel);
+
+ /**
+ * @get_modes:
+ *
+ * Add modes to the connector that the panel is attached to
+ * and returns the number of modes added.
+ *
+ * This function is mandatory.
+ */
+ int (*get_modes)(struct drm_panel *panel,
+ struct drm_connector *connector);
+
+ /**
+ * @get_timings:
+ *
+ * Copy display timings into the provided array and return
+ * the number of display timings available.
+ *
+ * This function is optional.
+ */
int (*get_timings)(struct drm_panel *panel, unsigned int num_timings,
struct display_timing *timings);
};
/**
* struct drm_panel - DRM panel object
- * @drm: DRM device owning the panel
- * @connector: DRM connector that the panel is attached to
- * @dev: parent device of the panel
- * @funcs: operations that can be performed on the panel
- * @list: panel entry in registry
*/
struct drm_panel {
- struct drm_device *drm;
- struct drm_connector *connector;
+ /**
+ * @dev:
+ *
+ * Parent device of the panel.
+ */
struct device *dev;
+ /**
+ * @backlight:
+ *
+ * Backlight device, used to turn on backlight after the call
+ * to enable(), and to turn off backlight before the call to
+ * disable().
+ * backlight is set by drm_panel_of_backlight() and drivers
+ * shall not assign it.
+ */
+ struct backlight_device *backlight;
+
+ /**
+ * @funcs:
+ *
+ * Operations that can be performed on the panel.
+ */
const struct drm_panel_funcs *funcs;
+ /**
+ * @connector_type:
+ *
+ * Type of the panel as a DRM_MODE_CONNECTOR_* value. This is used to
+ * initialise the drm_connector corresponding to the panel with the
+ * correct connector type.
+ */
+ int connector_type;
+
+ /**
+ * @list:
+ *
+ * Panel entry in registry.
+ */
struct list_head list;
};
-/**
- * drm_disable_unprepare - power off a panel
- * @panel: DRM panel
- *
- * Calling this function will completely power off a panel (assert the panel's
- * reset, turn off power supplies, ...). After this function has completed, it
- * is usually no longer possible to communicate with the panel until another
- * call to drm_panel_prepare().
- *
- * Return: 0 on success or a negative error code on failure.
- */
-static inline int drm_panel_unprepare(struct drm_panel *panel)
-{
- if (panel && panel->funcs && panel->funcs->unprepare)
- return panel->funcs->unprepare(panel);
-
- return panel ? -ENOSYS : -EINVAL;
-}
-
-/**
- * drm_panel_disable - disable a panel
- * @panel: DRM panel
- *
- * This will typically turn off the panel's backlight or disable the display
- * drivers. For smart panels it should still be possible to communicate with
- * the integrated circuitry via any command bus after this call.
- *
- * Return: 0 on success or a negative error code on failure.
- */
-static inline int drm_panel_disable(struct drm_panel *panel)
-{
- if (panel && panel->funcs && panel->funcs->disable)
- return panel->funcs->disable(panel);
-
- return panel ? -ENOSYS : -EINVAL;
-}
-
-/**
- * drm_panel_prepare - power on a panel
- * @panel: DRM panel
- *
- * Calling this function will enable power and deassert any reset signals to
- * the panel. After this has completed it is possible to communicate with any
- * integrated circuitry via a command bus.
- *
- * Return: 0 on success or a negative error code on failure.
- */
-static inline int drm_panel_prepare(struct drm_panel *panel)
-{
- if (panel && panel->funcs && panel->funcs->prepare)
- return panel->funcs->prepare(panel);
-
- return panel ? -ENOSYS : -EINVAL;
-}
-
-/**
- * drm_panel_enable - enable a panel
- * @panel: DRM panel
- *
- * Calling this function will cause the panel display drivers to be turned on
- * and the backlight to be enabled. Content will be visible on screen after
- * this call completes.
- *
- * Return: 0 on success or a negative error code on failure.
- */
-static inline int drm_panel_enable(struct drm_panel *panel)
-{
- if (panel && panel->funcs && panel->funcs->enable)
- return panel->funcs->enable(panel);
-
- return panel ? -ENOSYS : -EINVAL;
-}
-
-/**
- * drm_panel_get_modes - probe the available display modes of a panel
- * @panel: DRM panel
- *
- * The modes probed from the panel are automatically added to the connector
- * that the panel is attached to.
- *
- * Return: The number of modes available from the panel on success or a
- * negative error code on failure.
- */
-static inline int drm_panel_get_modes(struct drm_panel *panel)
-{
- if (panel && panel->funcs && panel->funcs->get_modes)
- return panel->funcs->get_modes(panel);
-
- return panel ? -ENOSYS : -EINVAL;
-}
-
-void drm_panel_init(struct drm_panel *panel);
+void drm_panel_init(struct drm_panel *panel, struct device *dev,
+ const struct drm_panel_funcs *funcs,
+ int connector_type);
int drm_panel_add(struct drm_panel *panel);
void drm_panel_remove(struct drm_panel *panel);
int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector);
-int drm_panel_detach(struct drm_panel *panel);
+void drm_panel_detach(struct drm_panel *panel);
+
+int drm_panel_prepare(struct drm_panel *panel);
+int drm_panel_unprepare(struct drm_panel *panel);
+
+int drm_panel_enable(struct drm_panel *panel);
+int drm_panel_disable(struct drm_panel *panel);
+
+int drm_panel_get_modes(struct drm_panel *panel, struct drm_connector *connector);
#if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL)
struct drm_panel *of_drm_find_panel(const struct device_node *np);
@@ -204,4 +198,14 @@ static inline struct drm_panel *of_drm_find_panel(const struct device_node *np)
}
#endif
+#if IS_ENABLED(CONFIG_DRM_PANEL) && (IS_BUILTIN(CONFIG_BACKLIGHT_CLASS_DEVICE) || \
+ (IS_MODULE(CONFIG_DRM) && IS_MODULE(CONFIG_BACKLIGHT_CLASS_DEVICE)))
+int drm_panel_of_backlight(struct drm_panel *panel);
+#else
+static inline int drm_panel_of_backlight(struct drm_panel *panel)
+{
+ return 0;
+}
+#endif
+
#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_pci.h b/sys/dev/pci/drm/include/drm/drm_pci.h
new file mode 100644
index 00000000000..3941b0255ec
--- /dev/null
+++ b/sys/dev/pci/drm/include/drm/drm_pci.h
@@ -0,0 +1,63 @@
+/*
+ * Internal Header for the Direct Rendering Manager
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * Copyright (c) 2009-2010, Code Aurora Forum.
+ * All rights reserved.
+ *
+ * Author: Rickard E. (Rik) Faith <faith@valinux.com>
+ * Author: Gareth Hughes <gareth@valinux.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DRM_PCI_H_
+#define _DRM_PCI_H_
+
+#include <linux/pci.h>
+
+struct drm_dma_handle;
+struct drm_device;
+struct drm_driver;
+struct drm_master;
+
+#ifdef CONFIG_PCI
+
+struct drm_dma_handle *drm_pci_alloc(struct drm_device *dev, size_t size,
+ size_t align);
+void drm_pci_free(struct drm_device *dev, struct drm_dma_handle * dmah);
+
+#else
+
+static inline struct drm_dma_handle *drm_pci_alloc(struct drm_device *dev,
+ size_t size, size_t align)
+{
+ return NULL;
+}
+
+static inline void drm_pci_free(struct drm_device *dev,
+ struct drm_dma_handle *dmah)
+{
+}
+
+#endif
+
+#endif /* _DRM_PCI_H_ */
diff --git a/sys/dev/pci/drm/include/drm/drm_plane.h b/sys/dev/pci/drm/include/drm/drm_plane.h
index 8a152dc16ea..3f396d94afe 100644
--- a/sys/dev/pci/drm/include/drm/drm_plane.h
+++ b/sys/dev/pci/drm/include/drm/drm_plane.h
@@ -27,6 +27,9 @@
#include <linux/ctype.h>
#include <drm/drm_mode_object.h>
#include <drm/drm_color_mgmt.h>
+#include <drm/drm_rect.h>
+#include <drm/drm_modeset_lock.h>
+#include <drm/drm_util.h>
struct drm_crtc;
struct drm_printer;
@@ -66,7 +69,7 @@ struct drm_plane_state {
*
* Optional fence to wait for before scanning out @fb. The core atomic
* code will set this when userspace is using explicit fencing. Do not
- * write this directly for a driver's implicit fence, use
+ * write this field directly for a driver's implicit fence, use
* drm_atomic_set_fence_for_plane() to ensure that an explicit fence is
* preserved.
*
@@ -119,6 +122,14 @@ struct drm_plane_state {
u16 alpha;
/**
+ * @pixel_blend_mode:
+ * The alpha blending equation selection, describing how the pixels from
+ * the current plane are composited with the background. Value can be
+ * one of DRM_MODE_BLEND_*
+ */
+ uint16_t pixel_blend_mode;
+
+ /**
* @rotation:
* Rotation of the plane. See drm_plane_create_rotation_property() for
* more details.
@@ -129,10 +140,11 @@ struct drm_plane_state {
* @zpos:
* Priority of the given plane on crtc (optional).
*
- * Note that multiple active planes on the same crtc can have an
- * identical zpos value. The rule to solving the conflict is to compare
- * the plane object IDs; the plane with a higher ID must be stacked on
- * top of a plane with a lower ID.
+ * User-space may set mutable zpos properties so that multiple active
+ * planes on the same CRTC have identical zpos values. This is a
+ * user-space bug, but drivers can solve the conflict by comparing the
+ * plane object IDs; the plane with a higher ID is stacked on top of a
+ * plane with a lower ID.
*
* See drm_plane_create_zpos_property() and
* drm_plane_create_zpos_immutable_property() for more details.
@@ -162,8 +174,36 @@ struct drm_plane_state {
*/
enum drm_color_range color_range;
- /** @src: clipped source coordinates of the plane (in 16.16) */
- /** @dst: clipped destination coordinates of the plane */
+ /**
+ * @fb_damage_clips:
+ *
+ * Blob representing damage (area in plane framebuffer that changed
+ * since last plane update) as an array of &drm_mode_rect in framebuffer
+ * coodinates of the attached framebuffer. Note that unlike plane src,
+ * damage clips are not in 16.16 fixed point.
+ */
+ struct drm_property_blob *fb_damage_clips;
+
+ /**
+ * @src:
+ *
+ * source coordinates of the plane (in 16.16).
+ *
+ * When using drm_atomic_helper_check_plane_state(),
+ * the coordinates are clipped, but the driver may choose
+ * to use unclipped coordinates instead when the hardware
+ * performs the clipping automatically.
+ */
+ /**
+ * @dst:
+ *
+ * clipped destination coordinates of the plane.
+ *
+ * When using drm_atomic_helper_check_plane_state(),
+ * the coordinates are clipped, but the driver may choose
+ * to use unclipped coordinates instead when the hardware
+ * performs the clipping automatically.
+ */
struct drm_rect src, dst;
/**
@@ -659,6 +699,14 @@ struct drm_plane {
* drm_plane_create_rotation_property().
*/
struct drm_property *rotation_property;
+ /**
+ * @blend_mode_property:
+ * Optional "pixel blend mode" enum property for this plane.
+ * Blend mode property represents the alpha blending equation selection,
+ * describing how the pixels from the current plane are composited with
+ * the background.
+ */
+ struct drm_property *blend_mode_property;
/**
* @color_encoding_property:
@@ -779,5 +827,39 @@ static inline struct drm_plane *drm_plane_find(struct drm_device *dev,
#define drm_for_each_plane(plane, dev) \
list_for_each_entry(plane, &(dev)->mode_config.plane_list, head)
+bool drm_any_plane_has_format(struct drm_device *dev,
+ u32 format, u64 modifier);
+/**
+ * drm_plane_get_damage_clips_count - Returns damage clips count.
+ * @state: Plane state.
+ *
+ * Simple helper to get the number of &drm_mode_rect clips set by user-space
+ * during plane update.
+ *
+ * Return: Number of clips in plane fb_damage_clips blob property.
+ */
+static inline unsigned int
+drm_plane_get_damage_clips_count(const struct drm_plane_state *state)
+{
+ return (state && state->fb_damage_clips) ?
+ state->fb_damage_clips->length/sizeof(struct drm_mode_rect) : 0;
+}
+
+/**
+ * drm_plane_get_damage_clips - Returns damage clips.
+ * @state: Plane state.
+ *
+ * Note that this function returns uapi type &drm_mode_rect. Drivers might
+ * instead be interested in internal &drm_rect which can be obtained by calling
+ * drm_helper_get_plane_damage_clips().
+ *
+ * Return: Damage clips in plane fb_damage_clips blob property.
+ */
+static inline struct drm_mode_rect *
+drm_plane_get_damage_clips(const struct drm_plane_state *state)
+{
+ return (struct drm_mode_rect *)((state && state->fb_damage_clips) ?
+ state->fb_damage_clips->data : NULL);
+}
#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_plane_helper.h b/sys/dev/pci/drm/include/drm/drm_plane_helper.h
index 26cee293478..331ebd60b3a 100644
--- a/sys/dev/pci/drm/include/drm/drm_plane_helper.h
+++ b/sys/dev/pci/drm/include/drm/drm_plane_helper.h
@@ -38,42 +38,7 @@
*/
#define DRM_PLANE_HELPER_NO_SCALING (1<<16)
-int drm_plane_helper_check_update(struct drm_plane *plane,
- struct drm_crtc *crtc,
- struct drm_framebuffer *fb,
- struct drm_rect *src,
- struct drm_rect *dest,
- unsigned int rotation,
- int min_scale,
- int max_scale,
- bool can_position,
- bool can_update_disabled,
- bool *visible);
-int drm_primary_helper_update(struct drm_plane *plane,
- struct drm_crtc *crtc,
- struct drm_framebuffer *fb,
- int crtc_x, int crtc_y,
- unsigned int crtc_w, unsigned int crtc_h,
- uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h,
- struct drm_modeset_acquire_ctx *ctx);
-int drm_primary_helper_disable(struct drm_plane *plane,
- struct drm_modeset_acquire_ctx *ctx);
void drm_primary_helper_destroy(struct drm_plane *plane);
extern const struct drm_plane_funcs drm_primary_helper_funcs;
-int drm_plane_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
- struct drm_framebuffer *fb,
- int crtc_x, int crtc_y,
- unsigned int crtc_w, unsigned int crtc_h,
- uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h,
- struct drm_modeset_acquire_ctx *ctx);
-int drm_plane_helper_disable(struct drm_plane *plane,
- struct drm_modeset_acquire_ctx *ctx);
-
-/* For use by drm_crtc_helper.c */
-int drm_plane_helper_commit(struct drm_plane *plane,
- struct drm_plane_state *plane_state,
- struct drm_framebuffer *old_fb);
#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_prime.h b/sys/dev/pci/drm/include/drm/drm_prime.h
index 713c133bef3..e9d4af64f32 100644
--- a/sys/dev/pci/drm/include/drm/drm_prime.h
+++ b/sys/dev/pci/drm/include/drm/drm_prime.h
@@ -42,7 +42,6 @@
* This just contains the internal &struct dma_buf and handle caches for each
* &struct drm_file used by the PRIME core code.
*/
-
struct drm_prime_file_private {
/* private: */
struct rwlock lock;
@@ -62,26 +61,18 @@ struct drm_device;
struct drm_gem_object;
struct drm_file;
-struct device;
+/* core prime functions */
+struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev,
+ struct dma_buf_export_info *exp_info);
+void drm_gem_dmabuf_release(struct dma_buf *dma_buf);
-struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
- struct drm_gem_object *obj,
- int flags);
+int drm_gem_prime_fd_to_handle(struct drm_device *dev,
+ struct drm_file *file_priv, int prime_fd, uint32_t *handle);
int drm_gem_prime_handle_to_fd(struct drm_device *dev,
struct drm_file *file_priv, uint32_t handle, uint32_t flags,
int *prime_fd);
-struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
- struct dma_buf *dma_buf);
-
-struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev,
- struct dma_buf *dma_buf,
- struct device *attach_dev);
-int drm_gem_prime_fd_to_handle(struct drm_device *dev,
- struct drm_file *file_priv, int prime_fd, uint32_t *handle);
-struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev,
- struct dma_buf_export_info *exp_info);
-void drm_gem_dmabuf_release(struct dma_buf *dma_buf);
+/* helper functions for exporting */
int drm_gem_map_attach(struct dma_buf *dma_buf,
struct dma_buf_attachment *attach);
void drm_gem_map_detach(struct dma_buf *dma_buf,
@@ -93,19 +84,27 @@ void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
enum dma_data_direction dir);
void *drm_gem_dmabuf_vmap(struct dma_buf *dma_buf);
void drm_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr);
-void *drm_gem_dmabuf_kmap(struct dma_buf *dma_buf, unsigned long page_num);
-void drm_gem_dmabuf_kunmap(struct dma_buf *dma_buf, unsigned long page_num,
- void *addr);
+
#ifdef __linux__
+int drm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma);
int drm_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma);
#endif
-#ifdef notyet
-int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
- dma_addr_t *addrs, int max_pages);
-struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_pages);
-#endif
+struct sg_table *drm_prime_pages_to_sg(struct vm_page **pages, unsigned int nr_pages);
+struct dma_buf *drm_gem_prime_export(struct drm_gem_object *obj,
+ int flags);
+
+/* helper functions for importing */
+struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev,
+ struct dma_buf *dma_buf,
+ struct device *attach_dev);
+struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
+ struct dma_buf *dma_buf);
+
void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg);
+int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct vm_page **pages,
+ dma_addr_t *addrs, int max_pages);
+
#endif /* __DRM_PRIME_H__ */
diff --git a/sys/dev/pci/drm/include/drm/drm_print.h b/sys/dev/pci/drm/include/drm/drm_print.h
index e37cd6c8f64..ca7cee8e728 100644
--- a/sys/dev/pci/drm/include/drm/drm_print.h
+++ b/sys/dev/pci/drm/include/drm/drm_print.h
@@ -30,6 +30,12 @@
#include <linux/printk.h>
#include <linux/seq_file.h>
#include <linux/device.h>
+#include <linux/debugfs.h>
+
+#include <drm/drm.h>
+
+/* Do *not* use outside of drm_print.[ch]! */
+extern unsigned int __drm_debug;
/**
* DOC: print
@@ -80,10 +86,14 @@ void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf);
void __drm_puts_seq_file(struct drm_printer *p, const char *str);
void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf);
void __drm_printfn_debug(struct drm_printer *p, struct va_format *vaf);
+void __drm_printfn_err(struct drm_printer *p, struct va_format *vaf);
__printf(2, 3)
void drm_printf(struct drm_printer *p, const char *f, ...);
void drm_puts(struct drm_printer *p, const char *str);
+void drm_print_regset32(struct drm_printer *p, struct debugfs_regset32 *regset);
+void drm_print_bits(struct drm_printer *p, unsigned long value,
+ const char * const bits[], unsigned int nbits);
__printf(2, 0)
/**
@@ -223,86 +233,106 @@ static inline struct drm_printer drm_debug_printer(const char *prefix)
return p;
}
-/*
- * The following categories are defined:
+/**
+ * drm_err_printer - construct a &drm_printer that outputs to pr_err()
+ * @prefix: debug output prefix
*
- * CORE: Used in the generic drm code: drm_ioctl.c, drm_mm.c, drm_memory.c, ...
- * This is the category used by the DRM_DEBUG() macro.
+ * RETURNS:
+ * The &drm_printer object
+ */
+static inline struct drm_printer drm_err_printer(const char *prefix)
+{
+ struct drm_printer p = {
+ .printfn = __drm_printfn_err,
+ .prefix = prefix
+ };
+ return p;
+}
+
+/**
+ * enum drm_debug_category - The DRM debug categories
*
- * DRIVER: Used in the vendor specific part of the driver: i915, radeon, ...
- * This is the category used by the DRM_DEBUG_DRIVER() macro.
+ * Each of the DRM debug logging macros use a specific category, and the logging
+ * is filtered by the drm.debug module parameter. This enum specifies the values
+ * for the interface.
*
- * KMS: used in the modesetting code.
- * This is the category used by the DRM_DEBUG_KMS() macro.
+ * Each DRM_DEBUG_<CATEGORY> macro logs to DRM_UT_<CATEGORY> category, except
+ * DRM_DEBUG() logs to DRM_UT_CORE.
*
- * PRIME: used in the prime code.
- * This is the category used by the DRM_DEBUG_PRIME() macro.
+ * Enabling verbose debug messages is done through the drm.debug parameter, each
+ * category being enabled by a bit:
*
- * ATOMIC: used in the atomic code.
- * This is the category used by the DRM_DEBUG_ATOMIC() macro.
+ * - drm.debug=0x1 will enable CORE messages
+ * - drm.debug=0x2 will enable DRIVER messages
+ * - drm.debug=0x3 will enable CORE and DRIVER messages
+ * - ...
+ * - drm.debug=0x1ff will enable all messages
*
- * VBL: used for verbose debug message in the vblank code
- * This is the category used by the DRM_DEBUG_VBL() macro.
+ * An interesting feature is that it's possible to enable verbose logging at
+ * run-time by echoing the debug value in its sysfs node::
*
- * Enabling verbose debug messages is done through the drm.debug parameter,
- * each category being enabled by a bit.
+ * # echo 0xf > /sys/module/drm/parameters/debug
*
- * drm.debug=0x1 will enable CORE messages
- * drm.debug=0x2 will enable DRIVER messages
- * drm.debug=0x3 will enable CORE and DRIVER messages
- * ...
- * drm.debug=0x3f will enable all messages
+ */
+enum drm_debug_category {
+ /**
+ * @DRM_UT_CORE: Used in the generic drm code: drm_ioctl.c, drm_mm.c,
+ * drm_memory.c, ...
+ */
+ DRM_UT_CORE = 0x01,
+ /**
+ * @DRM_UT_DRIVER: Used in the vendor specific part of the driver: i915,
+ * radeon, ... macro.
+ */
+ DRM_UT_DRIVER = 0x02,
+ /**
+ * @DRM_UT_KMS: Used in the modesetting code.
+ */
+ DRM_UT_KMS = 0x04,
+ /**
+ * @DRM_UT_PRIME: Used in the prime code.
+ */
+ DRM_UT_PRIME = 0x08,
+ /**
+ * @DRM_UT_ATOMIC: Used in the atomic code.
+ */
+ DRM_UT_ATOMIC = 0x10,
+ /**
+ * @DRM_UT_VBL: Used for verbose debug message in the vblank code.
+ */
+ DRM_UT_VBL = 0x20,
+ /**
+ * @DRM_UT_STATE: Used for verbose atomic state debugging.
+ */
+ DRM_UT_STATE = 0x40,
+ /**
+ * @DRM_UT_LEASE: Used in the lease code.
+ */
+ DRM_UT_LEASE = 0x80,
+ /**
+ * @DRM_UT_DP: Used in the DP code.
+ */
+ DRM_UT_DP = 0x100,
+};
+
+static inline bool drm_debug_enabled(enum drm_debug_category category)
+{
+ return unlikely(__drm_debug & category);
+}
+
+/*
+ * struct device based logging
*
- * An interesting feature is that it's possible to enable verbose logging at
- * run-time by echoing the debug value in its sysfs node:
- * # echo 0xf > /sys/module/drm/parameters/debug
+ * Prefer drm_device based logging over device or prink based logging.
*/
-#define DRM_UT_NONE 0x00
-#define DRM_UT_CORE 0x01
-#define DRM_UT_DRIVER 0x02
-#define DRM_UT_KMS 0x04
-#define DRM_UT_PRIME 0x08
-#define DRM_UT_ATOMIC 0x10
-#define DRM_UT_VBL 0x20
-#define DRM_UT_STATE 0x40
-#define DRM_UT_LEASE 0x80
-#define DRM_UT_DP 0x100
__printf(3, 4)
void drm_dev_printk(const struct device *dev, const char *level,
const char *format, ...);
__printf(3, 4)
-void drm_dev_dbg(const struct device *dev, unsigned int category,
+void drm_dev_dbg(const struct device *dev, enum drm_debug_category category,
const char *format, ...);
-__printf(2, 3)
-void drm_dbg(unsigned int category, const char *format, ...);
-__printf(1, 2)
-void drm_err(const char *format, ...);
-
-/* Macros to make printk easier */
-
-#define _DRM_PRINTK(once, level, fmt, ...) \
- printk##once(KERN_##level "[" DRM_NAME "] " fmt, ##__VA_ARGS__)
-
-#ifdef DRMDEBUG
-#define DRM_INFO(fmt, ...) \
- _DRM_PRINTK(, INFO, fmt, ##__VA_ARGS__)
-#else
-#define DRM_INFO(fmt, arg...) do { } while(/* CONSTCOND */ 0)
-#endif
-#define DRM_NOTE(fmt, ...) \
- _DRM_PRINTK(, NOTICE, fmt, ##__VA_ARGS__)
-#define DRM_WARN(fmt, ...) \
- _DRM_PRINTK(, WARNING, fmt, ##__VA_ARGS__)
-
-#define DRM_INFO_ONCE(fmt, ...) \
- _DRM_PRINTK(_once, INFO, fmt, ##__VA_ARGS__)
-#define DRM_NOTE_ONCE(fmt, ...) \
- _DRM_PRINTK(_once, NOTICE, fmt, ##__VA_ARGS__)
-#define DRM_WARN_ONCE(fmt, ...) \
- _DRM_PRINTK(_once, WARNING, fmt, ##__VA_ARGS__)
-
/**
* Error output.
*
@@ -311,8 +341,6 @@ void drm_err(const char *format, ...);
*/
#define DRM_DEV_ERROR(dev, fmt, ...) \
drm_dev_printk(dev, KERN_ERR, "*ERROR* " fmt, ##__VA_ARGS__)
-#define DRM_ERROR(fmt, ...) \
- drm_err(fmt, ##__VA_ARGS__)
/**
* Rate limited error output. Like DRM_ERROR() but won't flood the log.
@@ -329,10 +357,8 @@ void drm_err(const char *format, ...);
if (__ratelimit(&_rs)) \
DRM_DEV_ERROR(dev, fmt, ##__VA_ARGS__); \
})
-#define DRM_ERROR_RATELIMITED(fmt, ...) \
- DRM_DEV_ERROR_RATELIMITED(NULL, fmt, ##__VA_ARGS__)
-#define DRM_DEV_INFO(dev, fmt, ...) \
+#define DRM_DEV_INFO(dev, fmt, ...) \
drm_dev_printk(dev, KERN_INFO, fmt, ##__VA_ARGS__)
#define DRM_DEV_INFO_ONCE(dev, fmt, ...) \
@@ -352,91 +378,169 @@ void drm_err(const char *format, ...);
*/
#define DRM_DEV_DEBUG(dev, fmt, ...) \
drm_dev_dbg(dev, DRM_UT_CORE, fmt, ##__VA_ARGS__)
-#ifdef DRMDEBUG
-#define DRM_DEBUG(fmt, ...) \
- drm_dbg(DRM_UT_CORE, fmt, ##__VA_ARGS__)
-#else
-#define DRM_DEBUG(fmt, arg...) do { } while(/* CONSTCOND */ 0)
-#endif
-
#define DRM_DEV_DEBUG_DRIVER(dev, fmt, ...) \
drm_dev_dbg(dev, DRM_UT_DRIVER, fmt, ##__VA_ARGS__)
-#ifdef DRMDEBUG
-#define DRM_DEBUG_DRIVER(fmt, ...) \
- drm_dbg(DRM_UT_DRIVER, fmt, ##__VA_ARGS__)
-#else
-#define DRM_DEBUG_DRIVER(fmt, arg...) do { } while(/* CONSTCOND */ 0)
-#endif
-
#define DRM_DEV_DEBUG_KMS(dev, fmt, ...) \
drm_dev_dbg(dev, DRM_UT_KMS, fmt, ##__VA_ARGS__)
-#ifdef DRMDEBUG
+
+/*
+ * struct drm_device based logging
+ *
+ * Prefer drm_device based logging over device or prink based logging.
+ */
+
+/* Helper for struct drm_device based logging. */
+#define __drm_printk(drm, level, type, fmt, ...) \
+ dev_##level##type((drm)->dev, "[drm] " fmt, ##__VA_ARGS__)
+
+
+#define drm_info(drm, fmt, ...) \
+ __drm_printk((drm), info,, fmt, ##__VA_ARGS__)
+
+#define drm_notice(drm, fmt, ...) \
+ __drm_printk((drm), notice,, fmt, ##__VA_ARGS__)
+
+#define drm_warn(drm, fmt, ...) \
+ __drm_printk((drm), warn,, fmt, ##__VA_ARGS__)
+
+#define drm_err(drm, fmt, ...) \
+ __drm_printk((drm), err,, "*ERROR* " fmt, ##__VA_ARGS__)
+
+
+#define drm_info_once(drm, fmt, ...) \
+ __drm_printk((drm), info, _once, fmt, ##__VA_ARGS__)
+
+#define drm_notice_once(drm, fmt, ...) \
+ __drm_printk((drm), notice, _once, fmt, ##__VA_ARGS__)
+
+#define drm_warn_once(drm, fmt, ...) \
+ __drm_printk((drm), warn, _once, fmt, ##__VA_ARGS__)
+
+#define drm_err_once(drm, fmt, ...) \
+ __drm_printk((drm), err, _once, "*ERROR* " fmt, ##__VA_ARGS__)
+
+
+#define drm_err_ratelimited(drm, fmt, ...) \
+ __drm_printk((drm), err, _ratelimited, "*ERROR* " fmt, ##__VA_ARGS__)
+
+
+#define drm_dbg_core(drm, fmt, ...) \
+ drm_dev_dbg((drm)->dev, DRM_UT_CORE, fmt, ##__VA_ARGS__)
+#define drm_dbg(drm, fmt, ...) \
+ drm_dev_dbg((drm)->dev, DRM_UT_DRIVER, fmt, ##__VA_ARGS__)
+#define drm_dbg_kms(drm, fmt, ...) \
+ drm_dev_dbg((drm)->dev, DRM_UT_KMS, fmt, ##__VA_ARGS__)
+#define drm_dbg_prime(drm, fmt, ...) \
+ drm_dev_dbg((drm)->dev, DRM_UT_PRIME, fmt, ##__VA_ARGS__)
+#define drm_dbg_atomic(drm, fmt, ...) \
+ drm_dev_dbg((drm)->dev, DRM_UT_ATOMIC, fmt, ##__VA_ARGS__)
+#define drm_dbg_vbl(drm, fmt, ...) \
+ drm_dev_dbg((drm)->dev, DRM_UT_VBL, fmt, ##__VA_ARGS__)
+#define drm_dbg_state(drm, fmt, ...) \
+ drm_dev_dbg((drm)->dev, DRM_UT_STATE, fmt, ##__VA_ARGS__)
+#define drm_dbg_lease(drm, fmt, ...) \
+ drm_dev_dbg((drm)->dev, DRM_UT_LEASE, fmt, ##__VA_ARGS__)
+#define drm_dbg_dp(drm, fmt, ...) \
+ drm_dev_dbg((drm)->dev, DRM_UT_DP, fmt, ##__VA_ARGS__)
+
+
+/*
+ * printk based logging
+ *
+ * Prefer drm_device based logging over device or prink based logging.
+ */
+
+__printf(2, 3)
+void __drm_dbg(enum drm_debug_category category, const char *format, ...);
+__printf(1, 2)
+void __drm_err(const char *format, ...);
+
+/* Macros to make printk easier */
+
+#define _DRM_PRINTK(once, level, fmt, ...) \
+ printk##once(KERN_##level "[" DRM_NAME "] " fmt, ##__VA_ARGS__)
+
+#define DRM_INFO(fmt, ...) \
+ _DRM_PRINTK(, INFO, fmt, ##__VA_ARGS__)
+#define DRM_NOTE(fmt, ...) \
+ _DRM_PRINTK(, NOTICE, fmt, ##__VA_ARGS__)
+#define DRM_WARN(fmt, ...) \
+ _DRM_PRINTK(, WARNING, fmt, ##__VA_ARGS__)
+
+#define DRM_INFO_ONCE(fmt, ...) \
+ _DRM_PRINTK(_once, INFO, fmt, ##__VA_ARGS__)
+#define DRM_NOTE_ONCE(fmt, ...) \
+ _DRM_PRINTK(_once, NOTICE, fmt, ##__VA_ARGS__)
+#define DRM_WARN_ONCE(fmt, ...) \
+ _DRM_PRINTK(_once, WARNING, fmt, ##__VA_ARGS__)
+
+#define DRM_ERROR(fmt, ...) \
+ __drm_err(fmt, ##__VA_ARGS__)
+
+#define DRM_ERROR_RATELIMITED(fmt, ...) \
+ DRM_DEV_ERROR_RATELIMITED(NULL, fmt, ##__VA_ARGS__)
+
+#define DRM_DEBUG(fmt, ...) \
+ __drm_dbg(DRM_UT_CORE, fmt, ##__VA_ARGS__)
+
+#define DRM_DEBUG_DRIVER(fmt, ...) \
+ __drm_dbg(DRM_UT_DRIVER, fmt, ##__VA_ARGS__)
+
#define DRM_DEBUG_KMS(fmt, ...) \
- drm_dbg(DRM_UT_KMS, fmt, ##__VA_ARGS__)
-#else
-#define DRM_DEBUG_KMS(fmt, arg...) do { } while(/* CONSTCOND */ 0)
-#endif
+ __drm_dbg(DRM_UT_KMS, fmt, ##__VA_ARGS__)
-#define DRM_DEV_DEBUG_PRIME(dev, fmt, ...) \
- drm_dev_dbg(dev, DRM_UT_PRIME, fmt, ##__VA_ARGS__)
#define DRM_DEBUG_PRIME(fmt, ...) \
- drm_dbg(DRM_UT_PRIME, fmt, ##__VA_ARGS__)
+ __drm_dbg(DRM_UT_PRIME, fmt, ##__VA_ARGS__)
-#define DRM_DEV_DEBUG_ATOMIC(dev, fmt, ...) \
- drm_dev_dbg(dev, DRM_UT_ATOMIC, fmt, ##__VA_ARGS__)
#define DRM_DEBUG_ATOMIC(fmt, ...) \
- drm_dbg(DRM_UT_ATOMIC, fmt, ##__VA_ARGS__)
+ __drm_dbg(DRM_UT_ATOMIC, fmt, ##__VA_ARGS__)
-#define DRM_DEV_DEBUG_VBL(dev, fmt, ...) \
- drm_dev_dbg(dev, DRM_UT_VBL, fmt, ##__VA_ARGS__)
#define DRM_DEBUG_VBL(fmt, ...) \
- drm_dbg(DRM_UT_VBL, fmt, ##__VA_ARGS__)
+ __drm_dbg(DRM_UT_VBL, fmt, ##__VA_ARGS__)
#define DRM_DEBUG_LEASE(fmt, ...) \
- drm_dbg(DRM_UT_LEASE, fmt, ##__VA_ARGS__)
+ __drm_dbg(DRM_UT_LEASE, fmt, ##__VA_ARGS__)
-#define DRM_DEV_DEBUG_DP(dev, fmt, ...) \
- drm_dev_dbg(dev, DRM_UT_DP, fmt, ## __VA_ARGS__)
-#define DRM_DEBUG_DP(dev, fmt, ...) \
- drm_dbg(DRM_UT_DP, fmt, ## __VA_ARGS__)
+#define DRM_DEBUG_DP(fmt, ...) \
+ __drm_dbg(DRM_UT_DP, fmt, ## __VA_ARGS__)
-#define _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, category, fmt, ...) \
+
+#define DRM_DEBUG_KMS_RATELIMITED(fmt, ...) \
({ \
static DEFINE_RATELIMIT_STATE(_rs, \
- DEFAULT_RATELIMIT_INTERVAL, \
- DEFAULT_RATELIMIT_BURST); \
+ DEFAULT_RATELIMIT_INTERVAL, \
+ DEFAULT_RATELIMIT_BURST); \
if (__ratelimit(&_rs)) \
- drm_dev_dbg(dev, category, fmt, ##__VA_ARGS__); \
+ drm_dev_dbg(NULL, DRM_UT_KMS, fmt, ##__VA_ARGS__); \
})
-/**
- * Rate limited debug output. Like DRM_DEBUG() but won't flood the log.
+/*
+ * struct drm_device based WARNs
*
- * @dev: device pointer
- * @fmt: printf() like format string.
+ * drm_WARN*() acts like WARN*(), but with the key difference of
+ * using device specific information so that we know from which device
+ * warning is originating from.
+ *
+ * Prefer drm_device based drm_WARN* over regular WARN*
*/
-#define DRM_DEV_DEBUG_RATELIMITED(dev, fmt, ...) \
- _DEV_DRM_DEFINE_DEBUG_RATELIMITED(dev, DRM_UT_CORE, \
- fmt, ##__VA_ARGS__)
-#define DRM_DEBUG_RATELIMITED(fmt, ...) \
- DRM_DEV_DEBUG_RATELIMITED(NULL, fmt, ##__VA_ARGS__)
-
-#define DRM_DEV_DEBUG_DRIVER_RATELIMITED(dev, fmt, ...) \
- _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, DRM_UT_DRIVER, \
- fmt, ##__VA_ARGS__)
-#define DRM_DEBUG_DRIVER_RATELIMITED(fmt, ...) \
- DRM_DEV_DEBUG_DRIVER_RATELIMITED(NULL, fmt, ##__VA_ARGS__)
-
-#define DRM_DEV_DEBUG_KMS_RATELIMITED(dev, fmt, ...) \
- _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, DRM_UT_KMS, \
- fmt, ##__VA_ARGS__)
-#define DRM_DEBUG_KMS_RATELIMITED(fmt, ...) \
- DRM_DEV_DEBUG_KMS_RATELIMITED(NULL, fmt, ##__VA_ARGS__)
-#define DRM_DEV_DEBUG_PRIME_RATELIMITED(dev, fmt, ...) \
- _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, DRM_UT_PRIME, \
- fmt, ##__VA_ARGS__)
-#define DRM_DEBUG_PRIME_RATELIMITED(fmt, ...) \
- DRM_DEV_DEBUG_PRIME_RATELIMITED(NULL, fmt, ##__VA_ARGS__)
+/* Helper for struct drm_device based WARNs */
+#define drm_WARN(drm, condition, format, arg...) \
+ WARN(condition, "%s %s: " format, \
+ dev_driver_string((drm)->dev), \
+ dev_name((drm)->dev), ## arg)
+
+#define drm_WARN_ONCE(drm, condition, format, arg...) \
+ WARN_ONCE(condition, "%s %s: " format, \
+ dev_driver_string((drm)->dev), \
+ dev_name((drm)->dev), ## arg)
+
+#define drm_WARN_ON(drm, x) \
+ drm_WARN((drm), (x), "%s", \
+ "drm_WARN_ON(" __stringify(x) ")")
+
+#define drm_WARN_ON_ONCE(drm, x) \
+ drm_WARN_ONCE((drm), (x), "%s", \
+ "drm_WARN_ON_ONCE(" __stringify(x) ")")
#endif /* DRM_PRINT_H_ */
diff --git a/sys/dev/pci/drm/include/drm/drm_probe_helper.h b/sys/dev/pci/drm/include/drm/drm_probe_helper.h
new file mode 100644
index 00000000000..8d3ed2834d3
--- /dev/null
+++ b/sys/dev/pci/drm/include/drm/drm_probe_helper.h
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+
+#ifndef __DRM_PROBE_HELPER_H__
+#define __DRM_PROBE_HELPER_H__
+
+#include <linux/types.h>
+
+struct drm_connector;
+struct drm_device;
+struct drm_modeset_acquire_ctx;
+
+int drm_helper_probe_single_connector_modes(struct drm_connector
+ *connector, uint32_t maxX,
+ uint32_t maxY);
+int drm_helper_probe_detect(struct drm_connector *connector,
+ struct drm_modeset_acquire_ctx *ctx,
+ bool force);
+void drm_kms_helper_poll_init(struct drm_device *dev);
+void drm_kms_helper_poll_fini(struct drm_device *dev);
+bool drm_helper_hpd_irq_event(struct drm_device *dev);
+void drm_kms_helper_hotplug_event(struct drm_device *dev);
+
+void drm_kms_helper_poll_disable(struct drm_device *dev);
+void drm_kms_helper_poll_enable(struct drm_device *dev);
+bool drm_kms_helper_is_poll_worker(void);
+
+#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_property.h b/sys/dev/pci/drm/include/drm/drm_property.h
index c030f6ccab9..4a0a80d658c 100644
--- a/sys/dev/pci/drm/include/drm/drm_property.h
+++ b/sys/dev/pci/drm/include/drm/drm_property.h
@@ -27,6 +27,8 @@
#include <linux/ctype.h>
#include <drm/drm_mode_object.h>
+#include <uapi/drm/drm_mode.h>
+
/**
* struct drm_property_enum - symbolic values for enumerations
* @value: numeric property value for this enum entry
@@ -151,7 +153,8 @@ struct drm_property {
* userspace. The kernel is allowed to update the value of these
* properties. This is generally used to expose probe state to
* userspace, e.g. the EDID, or the connector path property on DP
- * MST sinks.
+ * MST sinks. Kernel can update the value of an immutable property
+ * by calling drm_object_property_set_value().
*/
uint32_t flags;
diff --git a/sys/dev/pci/drm/include/drm/drm_rect.h b/sys/dev/pci/drm/include/drm/drm_rect.h
index 6c54544a4be..57a3be9e53e 100644
--- a/sys/dev/pci/drm/include/drm/drm_rect.h
+++ b/sys/dev/pci/drm/include/drm/drm_rect.h
@@ -24,6 +24,8 @@
#ifndef DRM_RECT_H
#define DRM_RECT_H
+#include <linux/types.h>
+
/**
* DOC: rect utils
*
@@ -70,6 +72,23 @@ struct drm_rect {
(r)->y1 >> 16, (((r)->y1 & 0xffff) * 15625) >> 10
/**
+ * drm_rect_init - initialize the rectangle from x/y/w/h
+ * @r: rectangle
+ * @x: x coordinate
+ * @y: y coordinate
+ * @width: width
+ * @height: height
+ */
+static inline void drm_rect_init(struct drm_rect *r, int x, int y,
+ int width, int height)
+{
+ r->x1 = x;
+ r->y1 = y;
+ r->x2 = x + width;
+ r->y2 = y + height;
+}
+
+/**
* drm_rect_adjust_size - adjust the size of the rectangle
* @r: rectangle to be adjusted
* @dw: horizontal adjustment
@@ -107,6 +126,20 @@ static inline void drm_rect_translate(struct drm_rect *r, int dx, int dy)
}
/**
+ * drm_rect_translate_to - translate the rectangle to an absolute position
+ * @r: rectangle to be tranlated
+ * @x: horizontal position
+ * @y: vertical position
+ *
+ * Move rectangle @r to @x in the horizontal direction,
+ * and to @y in the vertical direction.
+ */
+static inline void drm_rect_translate_to(struct drm_rect *r, int x, int y)
+{
+ drm_rect_translate(r, x - r->x1, y - r->y1);
+}
+
+/**
* drm_rect_downscale - downscale a rectangle
* @r: rectangle to be downscaled
* @horz: horizontal downscale factor
@@ -182,12 +215,6 @@ int drm_rect_calc_hscale(const struct drm_rect *src,
int drm_rect_calc_vscale(const struct drm_rect *src,
const struct drm_rect *dst,
int min_vscale, int max_vscale);
-int drm_rect_calc_hscale_relaxed(struct drm_rect *src,
- struct drm_rect *dst,
- int min_hscale, int max_hscale);
-int drm_rect_calc_vscale_relaxed(struct drm_rect *src,
- struct drm_rect *dst,
- int min_vscale, int max_vscale);
void drm_rect_debug_print(const char *prefix,
const struct drm_rect *r, bool fixed_point);
void drm_rect_rotate(struct drm_rect *r,
diff --git a/sys/dev/pci/drm/include/drm/drm_scdc_helper.h b/sys/dev/pci/drm/include/drm/drm_scdc_helper.h
index f92eb2094d6..6a483533aae 100644
--- a/sys/dev/pci/drm/include/drm/drm_scdc_helper.h
+++ b/sys/dev/pci/drm/include/drm/drm_scdc_helper.h
@@ -50,9 +50,9 @@
#define SCDC_READ_REQUEST_ENABLE (1 << 0)
#define SCDC_STATUS_FLAGS_0 0x40
-#define SCDC_CH2_LOCK (1 < 3)
-#define SCDC_CH1_LOCK (1 < 2)
-#define SCDC_CH0_LOCK (1 < 1)
+#define SCDC_CH2_LOCK (1 << 3)
+#define SCDC_CH1_LOCK (1 << 2)
+#define SCDC_CH0_LOCK (1 << 1)
#define SCDC_CH_LOCK_MASK (SCDC_CH2_LOCK | SCDC_CH1_LOCK | SCDC_CH0_LOCK)
#define SCDC_CLOCK_DETECT (1 << 0)
diff --git a/sys/dev/pci/drm/include/drm/drm_self_refresh_helper.h b/sys/dev/pci/drm/include/drm/drm_self_refresh_helper.h
new file mode 100644
index 00000000000..520235c2070
--- /dev/null
+++ b/sys/dev/pci/drm/include/drm/drm_self_refresh_helper.h
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2019 Google, Inc.
+ *
+ * Authors:
+ * Sean Paul <seanpaul@chromium.org>
+ */
+#ifndef DRM_SELF_REFRESH_HELPER_H_
+#define DRM_SELF_REFRESH_HELPER_H_
+
+struct drm_atomic_state;
+struct drm_crtc;
+
+void drm_self_refresh_helper_alter_state(struct drm_atomic_state *state);
+void drm_self_refresh_helper_update_avg_times(struct drm_atomic_state *state,
+ unsigned int commit_time_ms,
+ unsigned int new_self_refresh_mask);
+
+int drm_self_refresh_helper_init(struct drm_crtc *crtc);
+void drm_self_refresh_helper_cleanup(struct drm_crtc *crtc);
+#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_syncobj.h b/sys/dev/pci/drm/include/drm/drm_syncobj.h
index 3980602472c..6cf7243a1dc 100644
--- a/sys/dev/pci/drm/include/drm/drm_syncobj.h
+++ b/sys/dev/pci/drm/include/drm/drm_syncobj.h
@@ -26,9 +26,10 @@
#ifndef __DRM_SYNCOBJ_H__
#define __DRM_SYNCOBJ_H__
-#include "linux/dma-fence.h"
+#include <linux/dma-fence.h>
+#include <linux/dma-fence-chain.h>
-struct drm_syncobj_cb;
+struct drm_file;
/**
* struct drm_syncobj - sync object.
@@ -62,25 +63,6 @@ struct drm_syncobj {
struct file *file;
};
-typedef void (*drm_syncobj_func_t)(struct drm_syncobj *syncobj,
- struct drm_syncobj_cb *cb);
-
-/**
- * struct drm_syncobj_cb - callback for drm_syncobj_add_callback
- * @node: used by drm_syncob_add_callback to append this struct to
- * &drm_syncobj.cb_list
- * @func: drm_syncobj_func_t to call
- *
- * This struct will be initialized by drm_syncobj_add_callback, additional
- * data can be passed along by embedding drm_syncobj_cb in another struct.
- * The callback will get called the next time drm_syncobj_replace_fence is
- * called.
- */
-struct drm_syncobj_cb {
- struct list_head node;
- drm_syncobj_func_t func;
-};
-
void drm_syncobj_free(struct kref *kref);
/**
@@ -131,15 +113,14 @@ drm_syncobj_fence_get(struct drm_syncobj *syncobj)
struct drm_syncobj *drm_syncobj_find(struct drm_file *file_private,
u32 handle);
-void drm_syncobj_add_callback(struct drm_syncobj *syncobj,
- struct drm_syncobj_cb *cb,
- drm_syncobj_func_t func);
-void drm_syncobj_remove_callback(struct drm_syncobj *syncobj,
- struct drm_syncobj_cb *cb);
+void drm_syncobj_add_point(struct drm_syncobj *syncobj,
+ struct dma_fence_chain *chain,
+ struct dma_fence *fence,
+ uint64_t point);
void drm_syncobj_replace_fence(struct drm_syncobj *syncobj,
struct dma_fence *fence);
int drm_syncobj_find_fence(struct drm_file *file_private,
- u32 handle,
+ u32 handle, u64 point, u64 flags,
struct dma_fence **fence);
void drm_syncobj_free(struct kref *kref);
int drm_syncobj_create(struct drm_syncobj **out_syncobj, uint32_t flags,
diff --git a/sys/dev/pci/drm/include/drm/drm_sysfs.h b/sys/dev/pci/drm/include/drm/drm_sysfs.h
new file mode 100644
index 00000000000..df8af5c4e47
--- /dev/null
+++ b/sys/dev/pci/drm/include/drm/drm_sysfs.h
@@ -0,0 +1,10 @@
+/* Public domain. */
+
+#ifndef _DRM_SYSFS_H_
+#define _DRM_SYSFS_H_
+
+struct drm_device;
+
+void drm_sysfs_hotplug_event(struct drm_device *);
+
+#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_util.h b/sys/dev/pci/drm/include/drm/drm_util.h
new file mode 100644
index 00000000000..79952d8c4bb
--- /dev/null
+++ b/sys/dev/pci/drm/include/drm/drm_util.h
@@ -0,0 +1,83 @@
+/*
+ * Internal Header for the Direct Rendering Manager
+ *
+ * Copyright 2018 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DRM_UTIL_H_
+#define _DRM_UTIL_H_
+
+/**
+ * DOC: drm utils
+ *
+ * Macros and inline functions that does not naturally belong in other places
+ */
+
+#include <linux/interrupt.h>
+#include <linux/kgdb.h>
+#include <linux/preempt.h>
+#include <linux/smp.h>
+
+/*
+ * Use EXPORT_SYMBOL_FOR_TESTS_ONLY() for functions that shall
+ * only be visible for drmselftests.
+ */
+#if defined(CONFIG_DRM_EXPORT_FOR_TESTS)
+#define EXPORT_SYMBOL_FOR_TESTS_ONLY(x) EXPORT_SYMBOL(x)
+#else
+#define EXPORT_SYMBOL_FOR_TESTS_ONLY(x)
+#endif
+
+/**
+ * for_each_if - helper for handling conditionals in various for_each macros
+ * @condition: The condition to check
+ *
+ * Typical use::
+ *
+ * #define for_each_foo_bar(x, y) \'
+ * list_for_each_entry(x, y->list, head) \'
+ * for_each_if(x->something == SOMETHING)
+ *
+ * The for_each_if() macro makes the use of for_each_foo_bar() less error
+ * prone.
+ */
+#define for_each_if(condition) if (!(condition)) {} else
+
+/**
+ * drm_can_sleep - returns true if currently okay to sleep
+ *
+ * This function shall not be used in new code.
+ * The check for running in atomic context may not work - see linux/preempt.h.
+ *
+ * FIXME: All users of drm_can_sleep should be removed (see todo.rst)
+ *
+ * Returns:
+ * False if kgdb is active, we are in atomic context or irqs are disabled.
+ */
+static inline bool drm_can_sleep(void)
+{
+ if (in_atomic() || in_dbg_master() || irqs_disabled())
+ return false;
+ return true;
+}
+
+#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_utils.h b/sys/dev/pci/drm/include/drm/drm_utils.h
index a803988d857..70775748d24 100644
--- a/sys/dev/pci/drm/include/drm/drm_utils.h
+++ b/sys/dev/pci/drm/include/drm/drm_utils.h
@@ -10,6 +10,10 @@
#ifndef __DRM_UTILS_H__
#define __DRM_UTILS_H__
+#include <linux/types.h>
+
int drm_get_panel_orientation_quirk(int width, int height);
+signed long drm_timeout_abs_to_jiffies(int64_t timeout_nsec);
+
#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_vblank.h b/sys/dev/pci/drm/include/drm/drm_vblank.h
index f731cca4447..925332d1865 100644
--- a/sys/dev/pci/drm/include/drm/drm_vblank.h
+++ b/sys/dev/pci/drm/include/drm/drm_vblank.h
@@ -30,7 +30,6 @@
#include <drm/drm_file.h>
#include <drm/drm_modes.h>
-#include <uapi/drm/drm.h>
struct drm_device;
struct drm_crtc;
@@ -95,7 +94,7 @@ struct drm_vblank_crtc {
/**
* @queue: Wait queue for vblank waiters.
*/
- wait_queue_head_t queue; /**< VBLANK wait queue */
+ wait_queue_head_t queue;
/**
* @disable_timer: Disable timer for the delayed vblank disabling
* hysteresis logic. Vblank disabling is controlled through the
@@ -107,12 +106,23 @@ struct drm_vblank_crtc {
/**
* @seqlock: Protect vblank count and time.
*/
- seqlock_t seqlock; /* protects vblank count and time */
+ seqlock_t seqlock;
/**
- * @count: Current software vblank counter.
+ * @count:
+ *
+ * Current software vblank counter.
+ *
+ * Note that for a given vblank counter value drm_crtc_handle_vblank()
+ * and drm_crtc_vblank_count() or drm_crtc_vblank_count_and_time()
+ * provide a barrier: Any writes done before calling
+ * drm_crtc_handle_vblank() will be visible to callers of the later
+ * functions, iff the vblank count is the same or a later one.
+ *
+ * IMPORTANT: This guarantee requires barriers, therefor never access
+ * this field directly. Use drm_crtc_vblank_count() instead.
*/
- u64 count;
+ atomic64_t count;
/**
* @time: Vblank timestamp corresponding to @count.
*/
@@ -123,7 +133,7 @@ struct drm_vblank_crtc {
* this refcount reaches 0 can the hardware interrupt be disabled using
* @disable_timer.
*/
- atomic_t refcount; /* number of users of vblank interruptsper crtc */
+ atomic_t refcount;
/**
* @last: Protected by &drm_device.vbl_lock, used for wraparound handling.
*/
@@ -156,7 +166,7 @@ struct drm_vblank_crtc {
* call drm_crtc_vblank_off() and drm_crtc_vblank_on(), which explicitly
* save and restore the vblank count.
*/
- unsigned int inmodeset; /* Display driver is setting mode */
+ unsigned int inmodeset;
/**
* @pipe: drm_crtc_index() of the &drm_crtc corresponding to this
* structure.
@@ -164,13 +174,13 @@ struct drm_vblank_crtc {
unsigned int pipe;
/**
* @framedur_ns: Frame/Field duration in ns, used by
- * drm_calc_vbltimestamp_from_scanoutpos() and computed by
+ * drm_crtc_vblank_helper_get_vblank_timestamp() and computed by
* drm_calc_timestamping_constants().
*/
int framedur_ns;
/**
* @linedur_ns: Line duration in ns, used by
- * drm_calc_vbltimestamp_from_scanoutpos() and computed by
+ * drm_crtc_vblank_helper_get_vblank_timestamp() and computed by
* drm_calc_timestamping_constants().
*/
int linedur_ns;
@@ -180,8 +190,8 @@ struct drm_vblank_crtc {
*
* Cache of the current hardware display mode. Only valid when @enabled
* is set. This is used by helpers like
- * drm_calc_vbltimestamp_from_scanoutpos(). We can't just access the
- * hardware mode by e.g. looking at &drm_crtc_state.adjusted_mode,
+ * drm_crtc_vblank_helper_get_vblank_timestamp(). We can't just access
+ * the hardware mode by e.g. looking at &drm_crtc_state.adjusted_mode,
* because that one is really hard to get from interrupt context.
*/
struct drm_display_mode hwmode;
@@ -196,6 +206,7 @@ struct drm_vblank_crtc {
};
int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs);
+bool drm_dev_has_vblank(const struct drm_device *dev);
u64 drm_crtc_vblank_count(struct drm_crtc *crtc);
u64 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc,
ktime_t *vblanktime);
@@ -219,13 +230,32 @@ u64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc);
void drm_vblank_restore(struct drm_device *dev, unsigned int pipe);
void drm_crtc_vblank_restore(struct drm_crtc *crtc);
-bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
- unsigned int pipe, int *max_error,
- ktime_t *vblank_time,
- bool in_vblank_irq);
void drm_calc_timestamping_constants(struct drm_crtc *crtc,
const struct drm_display_mode *mode);
wait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc);
void drm_crtc_set_max_vblank_count(struct drm_crtc *crtc,
u32 max_vblank_count);
+
+/*
+ * Helpers for struct drm_crtc_funcs
+ */
+
+typedef bool (*drm_vblank_get_scanout_position_func)(struct drm_crtc *crtc,
+ bool in_vblank_irq,
+ int *vpos, int *hpos,
+ ktime_t *stime,
+ ktime_t *etime,
+ const struct drm_display_mode *mode);
+
+bool
+drm_crtc_vblank_helper_get_vblank_timestamp_internal(struct drm_crtc *crtc,
+ int *max_error,
+ ktime_t *vblank_time,
+ bool in_vblank_irq,
+ drm_vblank_get_scanout_position_func get_scanout_position);
+bool drm_crtc_vblank_helper_get_vblank_timestamp(struct drm_crtc *crtc,
+ int *max_error,
+ ktime_t *vblank_time,
+ bool in_vblank_irq);
+
#endif
diff --git a/sys/dev/pci/drm/include/drm/drm_vma_manager.h b/sys/dev/pci/drm/include/drm/drm_vma_manager.h
index 1872c27f080..0a1812412b4 100644
--- a/sys/dev/pci/drm/include/drm/drm_vma_manager.h
+++ b/sys/dev/pci/drm/include/drm/drm_vma_manager.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: drm_vma_manager.h,v 1.2 2020/01/22 07:52:31 jsg Exp $ */
+/* $OpenBSD: drm_vma_manager.h,v 1.3 2020/06/08 04:48:14 jsg Exp $ */
#ifndef __DRM_VMA_MANAGER_H__
#define __DRM_VMA_MANAGER_H__
@@ -30,6 +30,20 @@
#include <linux/spinlock.h>
#include <linux/types.h>
+/* We make up offsets for buffer objects so we can recognize them at
+ * mmap time. pgoff in mmap is an unsigned long, so we need to make sure
+ * that the faked up offset will fit
+ */
+#if BITS_PER_LONG == 64
+#define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFFUL >> PAGE_SHIFT) + 1)
+#define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFFUL >> PAGE_SHIFT) * 256)
+#else
+#define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFUL >> PAGE_SHIFT) + 1)
+#define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFUL >> PAGE_SHIFT) * 16)
+#endif
+
+struct drm_file;
+
struct drm_vma_offset_file {
struct rb_node vm_rb;
struct file *vm_filp;
@@ -54,9 +68,6 @@ void drm_vma_offset_manager_init(struct drm_vma_offset_manager *mgr,
unsigned long page_offset, unsigned long size);
void drm_vma_offset_manager_destroy(struct drm_vma_offset_manager *mgr);
-struct drm_vma_offset_node *drm_vma_offset_lookup(struct drm_vma_offset_manager *mgr,
- unsigned long start,
- unsigned long pages);
struct drm_vma_offset_node *drm_vma_offset_lookup_locked(struct drm_vma_offset_manager *mgr,
unsigned long start,
unsigned long pages);
@@ -71,25 +82,25 @@ bool drm_vma_node_is_allowed(struct drm_vma_offset_node *node,
struct file *filp);
/**
- * drm_vma_offset_exact_lookup() - Look up node by exact address
+ * drm_vma_offset_exact_lookup_locked() - Look up node by exact address
* @mgr: Manager object
* @start: Start address (page-based, not byte-based)
* @pages: Size of object (page-based)
*
- * Same as drm_vma_offset_lookup() but does not allow any offset into the node.
+ * Same as drm_vma_offset_lookup_locked() but does not allow any offset into the node.
* It only returns the exact object with the given start address.
*
* RETURNS:
* Node at exact start address @start.
*/
static inline struct drm_vma_offset_node *
-drm_vma_offset_exact_lookup(struct drm_vma_offset_manager *mgr,
- unsigned long start,
- unsigned long pages)
+drm_vma_offset_exact_lookup_locked(struct drm_vma_offset_manager *mgr,
+ unsigned long start,
+ unsigned long pages)
{
struct drm_vma_offset_node *node;
- node = drm_vma_offset_lookup(mgr, start, pages);
+ node = drm_vma_offset_lookup_locked(mgr, start, pages);
return (node && node->vm_node.start == start) ? node : NULL;
}
@@ -97,7 +108,7 @@ drm_vma_offset_exact_lookup(struct drm_vma_offset_manager *mgr,
* drm_vma_offset_lock_lookup() - Lock lookup for extended private use
* @mgr: Manager object
*
- * Lock VMA manager for extended lookups. Only *_locked() VMA function calls
+ * Lock VMA manager for extended lookups. Only locked VMA function calls
* are allowed while holding this lock. All other contexts are blocked from VMA
* until the lock is released via drm_vma_offset_unlock_lookup().
*
@@ -108,13 +119,6 @@ drm_vma_offset_exact_lookup(struct drm_vma_offset_manager *mgr,
* not call any other VMA helpers while holding this lock.
*
* Note: You're in atomic-context while holding this lock!
- *
- * Example:
- * drm_vma_offset_lock_lookup(mgr);
- * node = drm_vma_offset_lookup_locked(mgr);
- * if (node)
- * kref_get_unless_zero(container_of(node, sth, entr));
- * drm_vma_offset_unlock_lookup(mgr);
*/
static inline void drm_vma_offset_lock_lookup(struct drm_vma_offset_manager *mgr)
{
@@ -186,19 +190,6 @@ static inline unsigned long drm_vma_node_size(struct drm_vma_offset_node *node)
}
/**
- * drm_vma_node_has_offset() - Check whether node is added to offset manager
- * @node: Node to be checked
- *
- * RETURNS:
- * true iff the node was previously allocated an offset and added to
- * an vma offset manager.
- */
-static inline bool drm_vma_node_has_offset(struct drm_vma_offset_node *node)
-{
- return drm_mm_node_allocated(&node->vm_node);
-}
-
-/**
* drm_vma_node_offset_addr() - Return sanitized offset for user-space mmaps
* @node: Linked offset node
*
@@ -222,8 +213,8 @@ static inline __u64 drm_vma_node_offset_addr(struct drm_vma_offset_node *node)
* @file_mapping: Address space to unmap @node from
*
* Unmap all userspace mappings for a given offset node. The mappings must be
- * associated with the @file_mapping address-space. If no offset exists or
- * the address-space is invalid, nothing is done.
+ * associated with the @file_mapping address-space. If no offset exists
+ * nothing is done.
*
* This call is unlocked. The caller must guarantee that drm_vma_offset_remove()
* is not called on this node concurrently.
@@ -231,7 +222,7 @@ static inline __u64 drm_vma_node_offset_addr(struct drm_vma_offset_node *node)
static inline void drm_vma_node_unmap(struct drm_vma_offset_node *node,
struct address_space *file_mapping)
{
- if (file_mapping && drm_vma_node_has_offset(node))
+ if (drm_mm_node_allocated(&node->vm_node))
unmap_mapping_range(file_mapping,
drm_vma_node_offset_addr(node),
drm_vma_node_size(node) << PAGE_SHIFT, 1);
diff --git a/sys/dev/pci/drm/include/drm/drm_writeback.h b/sys/dev/pci/drm/include/drm/drm_writeback.h
index 41e20c57771..64a01ba27ab 100644
--- a/sys/dev/pci/drm/include/drm/drm_writeback.h
+++ b/sys/dev/pci/drm/include/drm/drm_writeback.h
@@ -1,7 +1,7 @@
/* Public domain. */
-#ifndef DRM_WRITEBACK_H
-#define DRM_WRITEBACK_H
+#ifndef _DRM_WRITEBACK_H
+#define _DRM_WRITEBACK_H
#include <drm/drm_connector.h>
@@ -26,4 +26,21 @@ drm_writeback_get_out_fence(struct drm_writeback_connector *connector)
return NULL;
}
+static inline void
+drm_writeback_cleanup_job(struct drm_writeback_job *j)
+{
+}
+
+static inline int
+drm_writeback_prepare_job(struct drm_writeback_job *j)
+{
+ return 0;
+}
+
+static inline int
+drm_writeback_set_fb(struct drm_connector_state *cs, struct drm_framebuffer *fb)
+{
+ return 0;
+}
+
#endif
diff --git a/sys/dev/pci/drm/include/drm/gpu_scheduler.h b/sys/dev/pci/drm/include/drm/gpu_scheduler.h
index abbc5481430..2241239cd7a 100644
--- a/sys/dev/pci/drm/include/drm/gpu_scheduler.h
+++ b/sys/dev/pci/drm/include/drm/gpu_scheduler.h
@@ -26,6 +26,7 @@
#include <drm/spsc_queue.h>
#include <linux/dma-fence.h>
+#include <linux/completion.h>
#define MAX_WAIT_SCHED_ENTITY_Q_EMPTY msecs_to_jiffies(1000)
@@ -50,7 +51,11 @@ enum drm_sched_priority {
*
* @list: used to append this struct to the list of entities in the
* runqueue.
- * @rq: runqueue to which this entity belongs.
+ * @rq: runqueue on which this entity is currently scheduled.
+ * @sched_list: A list of schedulers (drm_gpu_schedulers).
+ * Jobs from this entity can be scheduled on any scheduler
+ * on this list.
+ * @num_sched_list: number of drm_gpu_schedulers in the sched_list.
* @rq_lock: lock to modify the runqueue to which this entity belongs.
* @job_queue: the list of jobs of this entity.
* @fence_seq: a linearly increasing seqno incremented with each
@@ -67,6 +72,8 @@ enum drm_sched_priority {
* @fini_status: contains the exit status in case the process was signalled.
* @last_scheduled: points to the finished fence of the last scheduled job.
* @last_user: last group leader pushing a job into the entity.
+ * @stopped: Marks the enity as removed from rq and destined for termination.
+ * @entity_idle: Signals when enityt is not in use
*
* Entities will emit jobs in order to their corresponding hardware
* ring, and the scheduler will alternate between entities based on
@@ -75,6 +82,9 @@ enum drm_sched_priority {
struct drm_sched_entity {
struct list_head list;
struct drm_sched_rq *rq;
+ struct drm_gpu_scheduler **sched_list;
+ unsigned int num_sched_list;
+ enum drm_sched_priority priority;
spinlock_t rq_lock;
struct spsc_queue job_queue;
@@ -91,6 +101,8 @@ struct drm_sched_entity {
#else
struct process *last_user;
#endif
+ bool stopped;
+ struct completion entity_idle;
};
/**
@@ -135,10 +147,6 @@ struct drm_sched_fence {
struct dma_fence finished;
/**
- * @cb: the callback for the parent fence below.
- */
- struct dma_fence_cb cb;
- /**
* @parent: the fence returned by &drm_sched_backend_ops.run_job
* when scheduling the job on hardware. We signal the
* &drm_sched_fence.finished fence once parent is signalled.
@@ -168,18 +176,14 @@ struct drm_sched_fence *to_drm_sched_fence(struct dma_fence *f);
* @sched: the scheduler instance on which this job is scheduled.
* @s_fence: contains the fences for the scheduling of job.
* @finish_cb: the callback for the finished fence.
- * @finish_work: schedules the function @drm_sched_job_finish once the job has
- * finished to remove the job from the
- * @drm_gpu_scheduler.ring_mirror_list.
* @node: used to append this struct to the @drm_gpu_scheduler.ring_mirror_list.
- * @work_tdr: schedules a delayed call to @drm_sched_job_timedout after the timeout
- * interval is over.
* @id: a unique id assigned to each job scheduled on the scheduler.
* @karma: increment on every hang caused by this job. If this exceeds the hang
* limit of the scheduler then the job is marked guilty and will not
* be scheduled further.
* @s_priority: the priority of the job.
* @entity: the entity to which this job belongs.
+ * @cb: the callback for the parent fence in s_fence.
*
* A job is created by the driver using drm_sched_job_init(), and
* should call drm_sched_entity_push_job() once it wants the scheduler
@@ -190,13 +194,12 @@ struct drm_sched_job {
struct drm_gpu_scheduler *sched;
struct drm_sched_fence *s_fence;
struct dma_fence_cb finish_cb;
- struct work_struct finish_work;
struct list_head node;
- struct delayed_work work_tdr;
uint64_t id;
atomic_t karma;
enum drm_sched_priority s_priority;
struct drm_sched_entity *entity;
+ struct dma_fence_cb cb;
};
static inline bool drm_sched_invalidate_job(struct drm_sched_job *s_job,
@@ -256,11 +259,16 @@ struct drm_sched_backend_ops {
* finished.
* @hw_rq_count: the number of jobs currently in the hardware queue.
* @job_id_count: used to assign unique id to the each job.
+ * @work_tdr: schedules a delayed call to @drm_sched_job_timedout after the
+ * timeout interval is over.
* @thread: the kthread on which the scheduler which run.
* @ring_mirror_list: the list of jobs which are currently in the job queue.
* @job_list_lock: lock to protect the ring_mirror_list.
* @hang_limit: once the hangs by a job crosses this limit then it is marked
* guilty and it will be considered for scheduling further.
+ * @num_jobs: the number of jobs in queue in the scheduler
+ * @ready: marks if the underlying HW is ready to work
+ * @free_guilty: A hit to time out handler to free the guilty job.
*
* One scheduler is implemented for each hardware ring.
*/
@@ -274,6 +282,7 @@ struct drm_gpu_scheduler {
wait_queue_head_t job_scheduled;
atomic_t hw_rq_count;
atomic64_t job_id_count;
+ struct delayed_work work_tdr;
#ifdef __linux__
struct task_struct *thread;
#else
@@ -282,38 +291,66 @@ struct drm_gpu_scheduler {
struct list_head ring_mirror_list;
spinlock_t job_list_lock;
int hang_limit;
+ atomic_t num_jobs;
+ bool ready;
+ bool free_guilty;
};
int drm_sched_init(struct drm_gpu_scheduler *sched,
const struct drm_sched_backend_ops *ops,
uint32_t hw_submission, unsigned hang_limit, long timeout,
const char *name);
+
void drm_sched_fini(struct drm_gpu_scheduler *sched);
+int drm_sched_job_init(struct drm_sched_job *job,
+ struct drm_sched_entity *entity,
+ void *owner);
+void drm_sched_entity_modify_sched(struct drm_sched_entity *entity,
+ struct drm_gpu_scheduler **sched_list,
+ unsigned int num_sched_list);
+
+void drm_sched_job_cleanup(struct drm_sched_job *job);
+void drm_sched_wakeup(struct drm_gpu_scheduler *sched);
+void drm_sched_stop(struct drm_gpu_scheduler *sched, struct drm_sched_job *bad);
+void drm_sched_start(struct drm_gpu_scheduler *sched, bool full_recovery);
+void drm_sched_resubmit_jobs(struct drm_gpu_scheduler *sched);
+void drm_sched_increase_karma(struct drm_sched_job *bad);
+bool drm_sched_dependency_optimized(struct dma_fence* fence,
+ struct drm_sched_entity *entity);
+void drm_sched_fault(struct drm_gpu_scheduler *sched);
+void drm_sched_job_kickout(struct drm_sched_job *s_job);
+
+void drm_sched_rq_add_entity(struct drm_sched_rq *rq,
+ struct drm_sched_entity *entity);
+void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,
+ struct drm_sched_entity *entity);
int drm_sched_entity_init(struct drm_sched_entity *entity,
- struct drm_sched_rq **rq_list,
- unsigned int num_rq_list,
+ enum drm_sched_priority priority,
+ struct drm_gpu_scheduler **sched_list,
+ unsigned int num_sched_list,
atomic_t *guilty);
long drm_sched_entity_flush(struct drm_sched_entity *entity, long timeout);
void drm_sched_entity_fini(struct drm_sched_entity *entity);
void drm_sched_entity_destroy(struct drm_sched_entity *entity);
+void drm_sched_entity_select_rq(struct drm_sched_entity *entity);
+struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity);
void drm_sched_entity_push_job(struct drm_sched_job *sched_job,
struct drm_sched_entity *entity);
-void drm_sched_entity_set_rq(struct drm_sched_entity *entity,
- struct drm_sched_rq *rq);
+void drm_sched_entity_set_priority(struct drm_sched_entity *entity,
+ enum drm_sched_priority priority);
+bool drm_sched_entity_is_ready(struct drm_sched_entity *entity);
struct drm_sched_fence *drm_sched_fence_create(
struct drm_sched_entity *s_entity, void *owner);
void drm_sched_fence_scheduled(struct drm_sched_fence *fence);
void drm_sched_fence_finished(struct drm_sched_fence *fence);
-int drm_sched_job_init(struct drm_sched_job *job,
- struct drm_sched_entity *entity,
- void *owner);
-void drm_sched_hw_job_reset(struct drm_gpu_scheduler *sched,
- struct drm_sched_job *job);
-void drm_sched_job_recovery(struct drm_gpu_scheduler *sched);
-bool drm_sched_dependency_optimized(struct dma_fence* fence,
- struct drm_sched_entity *entity);
-void drm_sched_job_kickout(struct drm_sched_job *s_job);
+
+unsigned long drm_sched_suspend_timeout(struct drm_gpu_scheduler *sched);
+void drm_sched_resume_timeout(struct drm_gpu_scheduler *sched,
+ unsigned long remaining);
+struct drm_gpu_scheduler *
+drm_sched_pick_best(struct drm_gpu_scheduler **sched_list,
+ unsigned int num_sched_list);
#endif
diff --git a/sys/dev/pci/drm/include/drm/i2c/ch7006.h b/sys/dev/pci/drm/include/drm/i2c/ch7006.h
new file mode 100644
index 00000000000..8390b437a1f
--- /dev/null
+++ b/sys/dev/pci/drm/include/drm/i2c/ch7006.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __DRM_I2C_CH7006_H__
+#define __DRM_I2C_CH7006_H__
+
+/**
+ * struct ch7006_encoder_params
+ *
+ * Describes how the ch7006 is wired up with the GPU. It should be
+ * used as the @params parameter of its @set_config method.
+ *
+ * See "http://www.chrontel.com/pdf/7006.pdf" for their precise
+ * meaning.
+ */
+struct ch7006_encoder_params {
+ enum {
+ CH7006_FORMAT_RGB16 = 0,
+ CH7006_FORMAT_YCrCb24m16,
+ CH7006_FORMAT_RGB24m16,
+ CH7006_FORMAT_RGB15,
+ CH7006_FORMAT_RGB24m12C,
+ CH7006_FORMAT_RGB24m12I,
+ CH7006_FORMAT_RGB24m8,
+ CH7006_FORMAT_RGB16m8,
+ CH7006_FORMAT_RGB15m8,
+ CH7006_FORMAT_YCrCb24m8,
+ } input_format;
+
+ enum {
+ CH7006_CLOCK_SLAVE = 0,
+ CH7006_CLOCK_MASTER,
+ } clock_mode;
+
+ enum {
+ CH7006_CLOCK_EDGE_NEG = 0,
+ CH7006_CLOCK_EDGE_POS,
+ } clock_edge;
+
+ int xcm, pcm;
+
+ enum {
+ CH7006_SYNC_SLAVE = 0,
+ CH7006_SYNC_MASTER,
+ } sync_direction;
+
+ enum {
+ CH7006_SYNC_SEPARATED = 0,
+ CH7006_SYNC_EMBEDDED,
+ } sync_encoding;
+
+ enum {
+ CH7006_POUT_1_8V = 0,
+ CH7006_POUT_3_3V,
+ } pout_level;
+
+ enum {
+ CH7006_ACTIVE_HSYNC = 0,
+ CH7006_ACTIVE_DSTART,
+ } active_detect;
+};
+
+#endif
diff --git a/sys/dev/pci/drm/include/drm/i2c/sil164.h b/sys/dev/pci/drm/include/drm/i2c/sil164.h
new file mode 100644
index 00000000000..205e27384c8
--- /dev/null
+++ b/sys/dev/pci/drm/include/drm/i2c/sil164.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2010 Francisco Jerez.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __DRM_I2C_SIL164_H__
+#define __DRM_I2C_SIL164_H__
+
+/**
+ * struct sil164_encoder_params
+ *
+ * Describes how the sil164 is connected to the GPU. It should be used
+ * as the @params parameter of its @set_config method.
+ *
+ * See "http://www.siliconimage.com/docs/SiI-DS-0021-E-164.pdf".
+ */
+struct sil164_encoder_params {
+ enum {
+ SIL164_INPUT_EDGE_FALLING = 0,
+ SIL164_INPUT_EDGE_RISING
+ } input_edge;
+
+ enum {
+ SIL164_INPUT_WIDTH_12BIT = 0,
+ SIL164_INPUT_WIDTH_24BIT
+ } input_width;
+
+ enum {
+ SIL164_INPUT_SINGLE_EDGE = 0,
+ SIL164_INPUT_DUAL_EDGE
+ } input_dual;
+
+ enum {
+ SIL164_PLL_FILTER_ON = 0,
+ SIL164_PLL_FILTER_OFF,
+ } pll_filter;
+
+ int input_skew; /** < Allowed range [-4, 3], use 0 for no de-skew. */
+ int duallink_skew; /** < Allowed range [-4, 3]. */
+};
+
+#endif
diff --git a/sys/dev/pci/drm/include/drm/i915_component.h b/sys/dev/pci/drm/include/drm/i915_component.h
index fca22d463e1..55c3b123581 100644
--- a/sys/dev/pci/drm/include/drm/i915_component.h
+++ b/sys/dev/pci/drm/include/drm/i915_component.h
@@ -26,10 +26,15 @@
#include "drm_audio_component.h"
+enum i915_component_type {
+ I915_COMPONENT_AUDIO = 1,
+ I915_COMPONENT_HDCP,
+};
+
/* MAX_PORT is the number of port
* It must be sync with I915_MAX_PORTS defined i915_drv.h
*/
-#define MAX_PORTS 6
+#define MAX_PORTS 9
/**
* struct i915_audio_component - Used for direct communication between i915 and hda drivers
diff --git a/sys/dev/pci/drm/include/drm/i915_drm.h b/sys/dev/pci/drm/include/drm/i915_drm.h
index c44703f471b..6722005884d 100644
--- a/sys/dev/pci/drm/include/drm/i915_drm.h
+++ b/sys/dev/pci/drm/include/drm/i915_drm.h
@@ -30,11 +30,11 @@
#include <uapi/drm/i915_drm.h>
/* For use by IPS driver */
-extern unsigned long i915_read_mch_val(void);
-extern bool i915_gpu_raise(void);
-extern bool i915_gpu_lower(void);
-extern bool i915_gpu_busy(void);
-extern bool i915_gpu_turbo_disable(void);
+unsigned long i915_read_mch_val(void);
+bool i915_gpu_raise(void);
+bool i915_gpu_lower(void);
+bool i915_gpu_busy(void);
+bool i915_gpu_turbo_disable(void);
/* Exported from arch/x86/kernel/early-quirks.c */
extern struct resource intel_graphics_stolen_res;
diff --git a/sys/dev/pci/drm/include/drm/i915_mei_hdcp_interface.h b/sys/dev/pci/drm/include/drm/i915_mei_hdcp_interface.h
new file mode 100644
index 00000000000..607fa40b9ae
--- /dev/null
+++ b/sys/dev/pci/drm/include/drm/i915_mei_hdcp_interface.h
@@ -0,0 +1,50 @@
+/* Public domain. */
+
+#ifndef _I915_MEI_HDCP_INTERFACE_H_
+#define _I915_MEI_HDCP_INTERFACE_H_
+
+#include <drm/drm_hdcp.h>
+
+enum hdcp_wired_protocol {
+ HDCP_PROTOCOL_INVALID,
+ HDCP_PROTOCOL_HDMI,
+ HDCP_PROTOCOL_DP
+};
+
+struct hdcp_port_data {
+ struct hdcp2_streamid_type *streams;
+ uint32_t seq_num_m;
+};
+
+struct i915_hdcp_component_ops {
+ int (*initiate_hdcp2_session)(struct device *, struct hdcp_port_data *,
+ struct hdcp2_ake_init *);
+ int (*verify_receiver_cert_prepare_km)(struct device *,
+ struct hdcp_port_data *, struct hdcp2_ake_send_cert *, bool *,
+ struct hdcp2_ake_no_stored_km *, size_t *);
+ int (*verify_hprime)(struct device *, struct hdcp_port_data *,
+ struct hdcp2_ake_send_hprime *);
+ int (*store_pairing_info)(struct device *, struct hdcp_port_data *,
+ struct hdcp2_ake_send_pairing_info *);
+ int (*initiate_locality_check)(struct device *, struct hdcp_port_data *,
+ struct hdcp2_lc_init *);
+ int (*verify_lprime)(struct device *, struct hdcp_port_data *,
+ struct hdcp2_lc_send_lprime *);
+ int (*get_session_key)(struct device *, struct hdcp_port_data *,
+ struct hdcp2_ske_send_eks *);
+ int (*repeater_check_flow_prepare_ack)(struct device *,
+ struct hdcp_port_data *, struct hdcp2_rep_send_receiverid_list *,
+ struct hdcp2_rep_send_ack *);
+ int (*verify_mprime)(struct device *, struct hdcp_port_data *,
+ struct hdcp2_rep_stream_ready *);
+ int (*enable_hdcp_authentication)(struct device *,
+ struct hdcp_port_data *);
+ int (*close_hdcp_session)(struct device *, struct hdcp_port_data *);
+};
+
+struct i915_hdcp_comp_master {
+ void *mei_dev;
+ const struct i915_hdcp_component_ops *ops;
+};
+
+#endif
diff --git a/sys/dev/pci/drm/include/drm/i915_pciids.h b/sys/dev/pci/drm/include/drm/i915_pciids.h
index ecbde04a68e..1d2c12219f4 100644
--- a/sys/dev/pci/drm/include/drm/i915_pciids.h
+++ b/sys/dev/pci/drm/include/drm/i915_pciids.h
@@ -108,8 +108,10 @@
INTEL_VGA_DEVICE(0x2e42, info), /* B43_G */ \
INTEL_VGA_DEVICE(0x2e92, info) /* B43_G.1 */
-#define INTEL_PINEVIEW_IDS(info) \
- INTEL_VGA_DEVICE(0xa001, info), \
+#define INTEL_PINEVIEW_G_IDS(info) \
+ INTEL_VGA_DEVICE(0xa001, info)
+
+#define INTEL_PINEVIEW_M_IDS(info) \
INTEL_VGA_DEVICE(0xa011, info)
#define INTEL_IRONLAKE_D_IDS(info) \
@@ -166,7 +168,18 @@
#define INTEL_IVB_Q_IDS(info) \
INTEL_QUANTA_VGA_DEVICE(info) /* Quanta transcode */
+#define INTEL_HSW_ULT_GT1_IDS(info) \
+ INTEL_VGA_DEVICE(0x0A02, info), /* ULT GT1 desktop */ \
+ INTEL_VGA_DEVICE(0x0A0A, info), /* ULT GT1 server */ \
+ INTEL_VGA_DEVICE(0x0A0B, info), /* ULT GT1 reserved */ \
+ INTEL_VGA_DEVICE(0x0A06, info) /* ULT GT1 mobile */
+
+#define INTEL_HSW_ULX_GT1_IDS(info) \
+ INTEL_VGA_DEVICE(0x0A0E, info) /* ULX GT1 mobile */
+
#define INTEL_HSW_GT1_IDS(info) \
+ INTEL_HSW_ULT_GT1_IDS(info), \
+ INTEL_HSW_ULX_GT1_IDS(info), \
INTEL_VGA_DEVICE(0x0402, info), /* GT1 desktop */ \
INTEL_VGA_DEVICE(0x040a, info), /* GT1 server */ \
INTEL_VGA_DEVICE(0x040B, info), /* GT1 reserved */ \
@@ -175,20 +188,26 @@
INTEL_VGA_DEVICE(0x0C0A, info), /* SDV GT1 server */ \
INTEL_VGA_DEVICE(0x0C0B, info), /* SDV GT1 reserved */ \
INTEL_VGA_DEVICE(0x0C0E, info), /* SDV GT1 reserved */ \
- INTEL_VGA_DEVICE(0x0A02, info), /* ULT GT1 desktop */ \
- INTEL_VGA_DEVICE(0x0A0A, info), /* ULT GT1 server */ \
- INTEL_VGA_DEVICE(0x0A0B, info), /* ULT GT1 reserved */ \
INTEL_VGA_DEVICE(0x0D02, info), /* CRW GT1 desktop */ \
INTEL_VGA_DEVICE(0x0D0A, info), /* CRW GT1 server */ \
INTEL_VGA_DEVICE(0x0D0B, info), /* CRW GT1 reserved */ \
INTEL_VGA_DEVICE(0x0D0E, info), /* CRW GT1 reserved */ \
INTEL_VGA_DEVICE(0x0406, info), /* GT1 mobile */ \
INTEL_VGA_DEVICE(0x0C06, info), /* SDV GT1 mobile */ \
- INTEL_VGA_DEVICE(0x0A06, info), /* ULT GT1 mobile */ \
- INTEL_VGA_DEVICE(0x0A0E, info), /* ULX GT1 mobile */ \
INTEL_VGA_DEVICE(0x0D06, info) /* CRW GT1 mobile */
+#define INTEL_HSW_ULT_GT2_IDS(info) \
+ INTEL_VGA_DEVICE(0x0A12, info), /* ULT GT2 desktop */ \
+ INTEL_VGA_DEVICE(0x0A1A, info), /* ULT GT2 server */ \
+ INTEL_VGA_DEVICE(0x0A1B, info), /* ULT GT2 reserved */ \
+ INTEL_VGA_DEVICE(0x0A16, info) /* ULT GT2 mobile */
+
+#define INTEL_HSW_ULX_GT2_IDS(info) \
+ INTEL_VGA_DEVICE(0x0A1E, info) /* ULX GT2 mobile */ \
+
#define INTEL_HSW_GT2_IDS(info) \
+ INTEL_HSW_ULT_GT2_IDS(info), \
+ INTEL_HSW_ULX_GT2_IDS(info), \
INTEL_VGA_DEVICE(0x0412, info), /* GT2 desktop */ \
INTEL_VGA_DEVICE(0x041a, info), /* GT2 server */ \
INTEL_VGA_DEVICE(0x041B, info), /* GT2 reserved */ \
@@ -197,9 +216,6 @@
INTEL_VGA_DEVICE(0x0C1A, info), /* SDV GT2 server */ \
INTEL_VGA_DEVICE(0x0C1B, info), /* SDV GT2 reserved */ \
INTEL_VGA_DEVICE(0x0C1E, info), /* SDV GT2 reserved */ \
- INTEL_VGA_DEVICE(0x0A12, info), /* ULT GT2 desktop */ \
- INTEL_VGA_DEVICE(0x0A1A, info), /* ULT GT2 server */ \
- INTEL_VGA_DEVICE(0x0A1B, info), /* ULT GT2 reserved */ \
INTEL_VGA_DEVICE(0x0D12, info), /* CRW GT2 desktop */ \
INTEL_VGA_DEVICE(0x0D1A, info), /* CRW GT2 server */ \
INTEL_VGA_DEVICE(0x0D1B, info), /* CRW GT2 reserved */ \
@@ -207,11 +223,17 @@
INTEL_VGA_DEVICE(0x0416, info), /* GT2 mobile */ \
INTEL_VGA_DEVICE(0x0426, info), /* GT2 mobile */ \
INTEL_VGA_DEVICE(0x0C16, info), /* SDV GT2 mobile */ \
- INTEL_VGA_DEVICE(0x0A16, info), /* ULT GT2 mobile */ \
- INTEL_VGA_DEVICE(0x0A1E, info), /* ULX GT2 mobile */ \
INTEL_VGA_DEVICE(0x0D16, info) /* CRW GT2 mobile */
+#define INTEL_HSW_ULT_GT3_IDS(info) \
+ INTEL_VGA_DEVICE(0x0A22, info), /* ULT GT3 desktop */ \
+ INTEL_VGA_DEVICE(0x0A2A, info), /* ULT GT3 server */ \
+ INTEL_VGA_DEVICE(0x0A2B, info), /* ULT GT3 reserved */ \
+ INTEL_VGA_DEVICE(0x0A26, info), /* ULT GT3 mobile */ \
+ INTEL_VGA_DEVICE(0x0A2E, info) /* ULT GT3 reserved */
+
#define INTEL_HSW_GT3_IDS(info) \
+ INTEL_HSW_ULT_GT3_IDS(info), \
INTEL_VGA_DEVICE(0x0422, info), /* GT3 desktop */ \
INTEL_VGA_DEVICE(0x042a, info), /* GT3 server */ \
INTEL_VGA_DEVICE(0x042B, info), /* GT3 reserved */ \
@@ -220,16 +242,11 @@
INTEL_VGA_DEVICE(0x0C2A, info), /* SDV GT3 server */ \
INTEL_VGA_DEVICE(0x0C2B, info), /* SDV GT3 reserved */ \
INTEL_VGA_DEVICE(0x0C2E, info), /* SDV GT3 reserved */ \
- INTEL_VGA_DEVICE(0x0A22, info), /* ULT GT3 desktop */ \
- INTEL_VGA_DEVICE(0x0A2A, info), /* ULT GT3 server */ \
- INTEL_VGA_DEVICE(0x0A2B, info), /* ULT GT3 reserved */ \
INTEL_VGA_DEVICE(0x0D22, info), /* CRW GT3 desktop */ \
INTEL_VGA_DEVICE(0x0D2A, info), /* CRW GT3 server */ \
INTEL_VGA_DEVICE(0x0D2B, info), /* CRW GT3 reserved */ \
INTEL_VGA_DEVICE(0x0D2E, info), /* CRW GT3 reserved */ \
INTEL_VGA_DEVICE(0x0C26, info), /* SDV GT3 mobile */ \
- INTEL_VGA_DEVICE(0x0A26, info), /* ULT GT3 mobile */ \
- INTEL_VGA_DEVICE(0x0A2E, info), /* ULT GT3 reserved */ \
INTEL_VGA_DEVICE(0x0D26, info) /* CRW GT3 mobile */
#define INTEL_HSW_IDS(info) \
@@ -245,35 +262,59 @@
INTEL_VGA_DEVICE(0x0157, info), \
INTEL_VGA_DEVICE(0x0155, info)
-#define INTEL_BDW_GT1_IDS(info) \
- INTEL_VGA_DEVICE(0x1602, info), /* GT1 ULT */ \
+#define INTEL_BDW_ULT_GT1_IDS(info) \
INTEL_VGA_DEVICE(0x1606, info), /* GT1 ULT */ \
- INTEL_VGA_DEVICE(0x160B, info), /* GT1 Iris */ \
- INTEL_VGA_DEVICE(0x160E, info), /* GT1 ULX */ \
+ INTEL_VGA_DEVICE(0x160B, info) /* GT1 Iris */
+
+#define INTEL_BDW_ULX_GT1_IDS(info) \
+ INTEL_VGA_DEVICE(0x160E, info) /* GT1 ULX */
+
+#define INTEL_BDW_GT1_IDS(info) \
+ INTEL_BDW_ULT_GT1_IDS(info), \
+ INTEL_BDW_ULX_GT1_IDS(info), \
+ INTEL_VGA_DEVICE(0x1602, info), /* GT1 ULT */ \
INTEL_VGA_DEVICE(0x160A, info), /* GT1 Server */ \
INTEL_VGA_DEVICE(0x160D, info) /* GT1 Workstation */
-#define INTEL_BDW_GT2_IDS(info) \
- INTEL_VGA_DEVICE(0x1612, info), /* GT2 Halo */ \
+#define INTEL_BDW_ULT_GT2_IDS(info) \
INTEL_VGA_DEVICE(0x1616, info), /* GT2 ULT */ \
- INTEL_VGA_DEVICE(0x161B, info), /* GT2 ULT */ \
- INTEL_VGA_DEVICE(0x161E, info), /* GT2 ULX */ \
+ INTEL_VGA_DEVICE(0x161B, info) /* GT2 ULT */
+
+#define INTEL_BDW_ULX_GT2_IDS(info) \
+ INTEL_VGA_DEVICE(0x161E, info) /* GT2 ULX */
+
+#define INTEL_BDW_GT2_IDS(info) \
+ INTEL_BDW_ULT_GT2_IDS(info), \
+ INTEL_BDW_ULX_GT2_IDS(info), \
+ INTEL_VGA_DEVICE(0x1612, info), /* GT2 Halo */ \
INTEL_VGA_DEVICE(0x161A, info), /* GT2 Server */ \
INTEL_VGA_DEVICE(0x161D, info) /* GT2 Workstation */
+#define INTEL_BDW_ULT_GT3_IDS(info) \
+ INTEL_VGA_DEVICE(0x1626, info), /* ULT */ \
+ INTEL_VGA_DEVICE(0x162B, info) /* Iris */ \
+
+#define INTEL_BDW_ULX_GT3_IDS(info) \
+ INTEL_VGA_DEVICE(0x162E, info) /* ULX */
+
#define INTEL_BDW_GT3_IDS(info) \
+ INTEL_BDW_ULT_GT3_IDS(info), \
+ INTEL_BDW_ULX_GT3_IDS(info), \
INTEL_VGA_DEVICE(0x1622, info), /* ULT */ \
- INTEL_VGA_DEVICE(0x1626, info), /* ULT */ \
- INTEL_VGA_DEVICE(0x162B, info), /* Iris */ \
- INTEL_VGA_DEVICE(0x162E, info), /* ULX */\
INTEL_VGA_DEVICE(0x162A, info), /* Server */ \
INTEL_VGA_DEVICE(0x162D, info) /* Workstation */
+#define INTEL_BDW_ULT_RSVD_IDS(info) \
+ INTEL_VGA_DEVICE(0x1636, info), /* ULT */ \
+ INTEL_VGA_DEVICE(0x163B, info) /* Iris */
+
+#define INTEL_BDW_ULX_RSVD_IDS(info) \
+ INTEL_VGA_DEVICE(0x163E, info) /* ULX */
+
#define INTEL_BDW_RSVD_IDS(info) \
+ INTEL_BDW_ULT_RSVD_IDS(info), \
+ INTEL_BDW_ULX_RSVD_IDS(info), \
INTEL_VGA_DEVICE(0x1632, info), /* ULT */ \
- INTEL_VGA_DEVICE(0x1636, info), /* ULT */ \
- INTEL_VGA_DEVICE(0x163B, info), /* Iris */ \
- INTEL_VGA_DEVICE(0x163E, info), /* ULX */ \
INTEL_VGA_DEVICE(0x163A, info), /* Server */ \
INTEL_VGA_DEVICE(0x163D, info) /* Workstation */
@@ -289,25 +330,40 @@
INTEL_VGA_DEVICE(0x22b2, info), \
INTEL_VGA_DEVICE(0x22b3, info)
+#define INTEL_SKL_ULT_GT1_IDS(info) \
+ INTEL_VGA_DEVICE(0x1906, info) /* ULT GT1 */
+
+#define INTEL_SKL_ULX_GT1_IDS(info) \
+ INTEL_VGA_DEVICE(0x190E, info) /* ULX GT1 */
+
#define INTEL_SKL_GT1_IDS(info) \
- INTEL_VGA_DEVICE(0x1906, info), /* ULT GT1 */ \
- INTEL_VGA_DEVICE(0x190E, info), /* ULX GT1 */ \
+ INTEL_SKL_ULT_GT1_IDS(info), \
+ INTEL_SKL_ULX_GT1_IDS(info), \
INTEL_VGA_DEVICE(0x1902, info), /* DT GT1 */ \
INTEL_VGA_DEVICE(0x190B, info), /* Halo GT1 */ \
INTEL_VGA_DEVICE(0x190A, info) /* SRV GT1 */
-#define INTEL_SKL_GT2_IDS(info) \
+#define INTEL_SKL_ULT_GT2_IDS(info) \
INTEL_VGA_DEVICE(0x1916, info), /* ULT GT2 */ \
- INTEL_VGA_DEVICE(0x1921, info), /* ULT GT2F */ \
- INTEL_VGA_DEVICE(0x191E, info), /* ULX GT2 */ \
+ INTEL_VGA_DEVICE(0x1921, info) /* ULT GT2F */
+
+#define INTEL_SKL_ULX_GT2_IDS(info) \
+ INTEL_VGA_DEVICE(0x191E, info) /* ULX GT2 */
+
+#define INTEL_SKL_GT2_IDS(info) \
+ INTEL_SKL_ULT_GT2_IDS(info), \
+ INTEL_SKL_ULX_GT2_IDS(info), \
INTEL_VGA_DEVICE(0x1912, info), /* DT GT2 */ \
INTEL_VGA_DEVICE(0x191B, info), /* Halo GT2 */ \
INTEL_VGA_DEVICE(0x191A, info), /* SRV GT2 */ \
INTEL_VGA_DEVICE(0x191D, info) /* WKS GT2 */
+#define INTEL_SKL_ULT_GT3_IDS(info) \
+ INTEL_VGA_DEVICE(0x1926, info) /* ULT GT3 */
+
#define INTEL_SKL_GT3_IDS(info) \
+ INTEL_SKL_ULT_GT3_IDS(info), \
INTEL_VGA_DEVICE(0x1923, info), /* ULT GT3 */ \
- INTEL_VGA_DEVICE(0x1926, info), /* ULT GT3 */ \
INTEL_VGA_DEVICE(0x1927, info), /* ULT GT3 */ \
INTEL_VGA_DEVICE(0x192B, info), /* Halo GT3 */ \
INTEL_VGA_DEVICE(0x192D, info) /* SRV GT3 */
@@ -336,29 +392,44 @@
INTEL_VGA_DEVICE(0x3184, info), \
INTEL_VGA_DEVICE(0x3185, info)
-#define INTEL_KBL_GT1_IDS(info) \
- INTEL_VGA_DEVICE(0x5913, info), /* ULT GT1.5 */ \
- INTEL_VGA_DEVICE(0x5915, info), /* ULX GT1.5 */ \
+#define INTEL_KBL_ULT_GT1_IDS(info) \
INTEL_VGA_DEVICE(0x5906, info), /* ULT GT1 */ \
+ INTEL_VGA_DEVICE(0x5913, info) /* ULT GT1.5 */
+
+#define INTEL_KBL_ULX_GT1_IDS(info) \
INTEL_VGA_DEVICE(0x590E, info), /* ULX GT1 */ \
+ INTEL_VGA_DEVICE(0x5915, info) /* ULX GT1.5 */
+
+#define INTEL_KBL_GT1_IDS(info) \
+ INTEL_KBL_ULT_GT1_IDS(info), \
+ INTEL_KBL_ULX_GT1_IDS(info), \
INTEL_VGA_DEVICE(0x5902, info), /* DT GT1 */ \
INTEL_VGA_DEVICE(0x5908, info), /* Halo GT1 */ \
INTEL_VGA_DEVICE(0x590B, info), /* Halo GT1 */ \
INTEL_VGA_DEVICE(0x590A, info) /* SRV GT1 */
-#define INTEL_KBL_GT2_IDS(info) \
+#define INTEL_KBL_ULT_GT2_IDS(info) \
INTEL_VGA_DEVICE(0x5916, info), /* ULT GT2 */ \
+ INTEL_VGA_DEVICE(0x5921, info) /* ULT GT2F */
+
+#define INTEL_KBL_ULX_GT2_IDS(info) \
+ INTEL_VGA_DEVICE(0x591E, info) /* ULX GT2 */
+
+#define INTEL_KBL_GT2_IDS(info) \
+ INTEL_KBL_ULT_GT2_IDS(info), \
+ INTEL_KBL_ULX_GT2_IDS(info), \
INTEL_VGA_DEVICE(0x5917, info), /* Mobile GT2 */ \
- INTEL_VGA_DEVICE(0x5921, info), /* ULT GT2F */ \
- INTEL_VGA_DEVICE(0x591E, info), /* ULX GT2 */ \
INTEL_VGA_DEVICE(0x5912, info), /* DT GT2 */ \
INTEL_VGA_DEVICE(0x591B, info), /* Halo GT2 */ \
INTEL_VGA_DEVICE(0x591A, info), /* SRV GT2 */ \
INTEL_VGA_DEVICE(0x591D, info) /* WKS GT2 */
+#define INTEL_KBL_ULT_GT3_IDS(info) \
+ INTEL_VGA_DEVICE(0x5926, info) /* ULT GT3 */
+
#define INTEL_KBL_GT3_IDS(info) \
+ INTEL_KBL_ULT_GT3_IDS(info), \
INTEL_VGA_DEVICE(0x5923, info), /* ULT GT3 */ \
- INTEL_VGA_DEVICE(0x5926, info), /* ULT GT3 */ \
INTEL_VGA_DEVICE(0x5927, info) /* ULT GT3 */
#define INTEL_KBL_GT4_IDS(info) \
@@ -375,27 +446,30 @@
/* CML GT1 */
#define INTEL_CML_GT1_IDS(info) \
- INTEL_VGA_DEVICE(0x9B21, info), \
- INTEL_VGA_DEVICE(0x9BAA, info), \
- INTEL_VGA_DEVICE(0x9BAB, info), \
- INTEL_VGA_DEVICE(0x9BAC, info), \
- INTEL_VGA_DEVICE(0x9BA0, info), \
INTEL_VGA_DEVICE(0x9BA5, info), \
INTEL_VGA_DEVICE(0x9BA8, info), \
INTEL_VGA_DEVICE(0x9BA4, info), \
INTEL_VGA_DEVICE(0x9BA2, info)
+#define INTEL_CML_U_GT1_IDS(info) \
+ INTEL_VGA_DEVICE(0x9B21, info), \
+ INTEL_VGA_DEVICE(0x9BAA, info), \
+ INTEL_VGA_DEVICE(0x9BAC, info)
+
/* CML GT2 */
#define INTEL_CML_GT2_IDS(info) \
- INTEL_VGA_DEVICE(0x9B41, info), \
- INTEL_VGA_DEVICE(0x9BCA, info), \
- INTEL_VGA_DEVICE(0x9BCB, info), \
- INTEL_VGA_DEVICE(0x9BCC, info), \
- INTEL_VGA_DEVICE(0x9BC0, info), \
INTEL_VGA_DEVICE(0x9BC5, info), \
INTEL_VGA_DEVICE(0x9BC8, info), \
INTEL_VGA_DEVICE(0x9BC4, info), \
- INTEL_VGA_DEVICE(0x9BC2, info)
+ INTEL_VGA_DEVICE(0x9BC2, info), \
+ INTEL_VGA_DEVICE(0x9BC6, info), \
+ INTEL_VGA_DEVICE(0x9BE6, info), \
+ INTEL_VGA_DEVICE(0x9BF6, info)
+
+#define INTEL_CML_U_GT2_IDS(info) \
+ INTEL_VGA_DEVICE(0x9B41, info), \
+ INTEL_VGA_DEVICE(0x9BCA, info), \
+ INTEL_VGA_DEVICE(0x9BCC, info)
#define INTEL_KBL_IDS(info) \
INTEL_KBL_GT1_IDS(info), \
@@ -462,10 +536,19 @@
INTEL_WHL_U_GT3_IDS(info), \
INTEL_AML_CFL_GT2_IDS(info), \
INTEL_CML_GT1_IDS(info), \
- INTEL_CML_GT2_IDS(info)
+ INTEL_CML_GT2_IDS(info), \
+ INTEL_CML_U_GT1_IDS(info), \
+ INTEL_CML_U_GT2_IDS(info)
/* CNL */
+#define INTEL_CNL_PORT_F_IDS(info) \
+ INTEL_VGA_DEVICE(0x5A54, info), \
+ INTEL_VGA_DEVICE(0x5A5C, info), \
+ INTEL_VGA_DEVICE(0x5A44, info), \
+ INTEL_VGA_DEVICE(0x5A4C, info)
+
#define INTEL_CNL_IDS(info) \
+ INTEL_CNL_PORT_F_IDS(info), \
INTEL_VGA_DEVICE(0x5A51, info), \
INTEL_VGA_DEVICE(0x5A59, info), \
INTEL_VGA_DEVICE(0x5A41, info), \
@@ -475,18 +558,12 @@
INTEL_VGA_DEVICE(0x5A42, info), \
INTEL_VGA_DEVICE(0x5A4A, info), \
INTEL_VGA_DEVICE(0x5A50, info), \
- INTEL_VGA_DEVICE(0x5A40, info), \
- INTEL_VGA_DEVICE(0x5A54, info), \
- INTEL_VGA_DEVICE(0x5A5C, info), \
- INTEL_VGA_DEVICE(0x5A44, info), \
- INTEL_VGA_DEVICE(0x5A4C, info)
+ INTEL_VGA_DEVICE(0x5A40, info)
/* ICL */
-#define INTEL_ICL_11_IDS(info) \
+#define INTEL_ICL_PORT_F_IDS(info) \
INTEL_VGA_DEVICE(0x8A50, info), \
- INTEL_VGA_DEVICE(0x8A51, info), \
INTEL_VGA_DEVICE(0x8A5C, info), \
- INTEL_VGA_DEVICE(0x8A5D, info), \
INTEL_VGA_DEVICE(0x8A59, info), \
INTEL_VGA_DEVICE(0x8A58, info), \
INTEL_VGA_DEVICE(0x8A52, info), \
@@ -495,6 +572,33 @@
INTEL_VGA_DEVICE(0x8A57, info), \
INTEL_VGA_DEVICE(0x8A56, info), \
INTEL_VGA_DEVICE(0x8A71, info), \
- INTEL_VGA_DEVICE(0x8A70, info)
+ INTEL_VGA_DEVICE(0x8A70, info), \
+ INTEL_VGA_DEVICE(0x8A53, info), \
+ INTEL_VGA_DEVICE(0x8A54, info)
+
+#define INTEL_ICL_11_IDS(info) \
+ INTEL_ICL_PORT_F_IDS(info), \
+ INTEL_VGA_DEVICE(0x8A51, info), \
+ INTEL_VGA_DEVICE(0x8A5D, info)
+
+/* EHL/JSL */
+#define INTEL_EHL_IDS(info) \
+ INTEL_VGA_DEVICE(0x4500, info), \
+ INTEL_VGA_DEVICE(0x4571, info), \
+ INTEL_VGA_DEVICE(0x4551, info), \
+ INTEL_VGA_DEVICE(0x4541, info), \
+ INTEL_VGA_DEVICE(0x4E71, info), \
+ INTEL_VGA_DEVICE(0x4E61, info), \
+ INTEL_VGA_DEVICE(0x4E51, info)
+
+/* TGL */
+#define INTEL_TGL_12_IDS(info) \
+ INTEL_VGA_DEVICE(0x9A49, info), \
+ INTEL_VGA_DEVICE(0x9A40, info), \
+ INTEL_VGA_DEVICE(0x9A59, info), \
+ INTEL_VGA_DEVICE(0x9A60, info), \
+ INTEL_VGA_DEVICE(0x9A68, info), \
+ INTEL_VGA_DEVICE(0x9A70, info), \
+ INTEL_VGA_DEVICE(0x9A78, info)
#endif /* _I915_PCIIDS_H */
diff --git a/sys/dev/pci/drm/include/drm/intel-gtt.h b/sys/dev/pci/drm/include/drm/intel-gtt.h
new file mode 100644
index 00000000000..b5bfb1c07f6
--- /dev/null
+++ b/sys/dev/pci/drm/include/drm/intel-gtt.h
@@ -0,0 +1,21 @@
+/* Public domain. */
+
+#ifndef _DRM_INTEL_GTT_H
+#define _DRM_INTEL_GTT_H
+
+#include <linux/agp_backend.h>
+#include <linux/kernel.h>
+
+struct pci_dev;
+
+int intel_enable_gtt(void);
+void intel_gtt_chipset_flush(void);
+int intel_gmch_probe(struct pci_dev *, struct pci_dev *, void *);
+void intel_gtt_get(u64 *, phys_addr_t *, resource_size_t *);
+void intel_gtt_insert_sg_entries(struct sg_table *, unsigned int,
+ unsigned int);
+void intel_gtt_insert_page(dma_addr_t, unsigned int, unsigned int);
+void intel_gtt_clear_range(unsigned int, unsigned int);
+void intel_gmch_remove(void);
+
+#endif
diff --git a/sys/dev/pci/drm/include/drm/task_barrier.h b/sys/dev/pci/drm/include/drm/task_barrier.h
new file mode 100644
index 00000000000..a2edc9a55d4
--- /dev/null
+++ b/sys/dev/pci/drm/include/drm/task_barrier.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2019 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include <linux/semaphore.h>
+#include <linux/atomic.h>
+
+/*
+ * Reusable 2 PHASE task barrier (randevouz point) implementation for N tasks.
+ * Based on the Little book of sempahores - https://greenteapress.com/wp/semaphores/
+ */
+
+
+
+#ifndef DRM_TASK_BARRIER_H_
+#define DRM_TASK_BARRIER_H_
+
+/*
+ * Represents an instance of a task barrier.
+ */
+struct task_barrier {
+ unsigned int n;
+ atomic_t count;
+ struct semaphore enter_turnstile;
+ struct semaphore exit_turnstile;
+};
+
+static inline void task_barrier_signal_turnstile(struct semaphore *turnstile,
+ unsigned int n)
+{
+ STUB();
+#ifdef notyet
+ int i;
+
+ for (i = 0 ; i < n; i++)
+ up(turnstile);
+#endif
+}
+
+static inline void task_barrier_init(struct task_barrier *tb)
+{
+ tb->n = 0;
+ atomic_set(&tb->count, 0);
+ STUB();
+#ifdef notyet
+ sema_init(&tb->enter_turnstile, 0);
+ sema_init(&tb->exit_turnstile, 0);
+#endif
+}
+
+static inline void task_barrier_add_task(struct task_barrier *tb)
+{
+ tb->n++;
+}
+
+static inline void task_barrier_rem_task(struct task_barrier *tb)
+{
+ tb->n--;
+}
+
+/*
+ * Lines up all the threads BEFORE the critical point.
+ *
+ * When all thread passed this code the entry barrier is back to locked state.
+ */
+static inline void task_barrier_enter(struct task_barrier *tb)
+{
+ if (atomic_inc_return(&tb->count) == tb->n)
+ task_barrier_signal_turnstile(&tb->enter_turnstile, tb->n);
+
+ STUB();
+#ifdef notyet
+ down(&tb->enter_turnstile);
+#endif
+}
+
+/*
+ * Lines up all the threads AFTER the critical point.
+ *
+ * This function is used to avoid any one thread running ahead if the barrier is
+ * used repeatedly .
+ */
+static inline void task_barrier_exit(struct task_barrier *tb)
+{
+ if (atomic_dec_return(&tb->count) == 0)
+ task_barrier_signal_turnstile(&tb->exit_turnstile, tb->n);
+
+ STUB();
+#ifdef notyet
+ down(&tb->exit_turnstile);
+#endif
+}
+
+/* Convinieince function when nothing to be done in between entry and exit */
+static inline void task_barrier_full(struct task_barrier *tb)
+{
+ task_barrier_enter(tb);
+ task_barrier_exit(tb);
+}
+
+#endif
diff --git a/sys/dev/pci/drm/include/drm/ttm/ttm_bo_api.h b/sys/dev/pci/drm/include/drm/ttm/ttm_bo_api.h
index a4004dfca30..675387a2be9 100644
--- a/sys/dev/pci/drm/include/drm/ttm/ttm_bo_api.h
+++ b/sys/dev/pci/drm/include/drm/ttm/ttm_bo_api.h
@@ -31,6 +31,7 @@
#ifndef _TTM_BO_API_H_
#define _TTM_BO_API_H_
+#include <drm/drm_gem.h>
#include <drm/drm_hashtab.h>
#include <drm/drm_vma_manager.h>
#include <linux/kref.h>
@@ -39,7 +40,9 @@
#include <linux/mutex.h>
#include <linux/mm.h>
#include <linux/bitmap.h>
-#include <linux/reservation.h>
+#include <linux/dma-resv.h>
+
+#include <uvm/uvm_extern.h>
struct ttm_bo_global;
@@ -51,6 +54,8 @@ struct ttm_placement;
struct ttm_place;
+struct ttm_lru_bulk_move;
+
/**
* struct ttm_bus_placement
*
@@ -126,34 +131,28 @@ struct ttm_tt;
/**
* struct ttm_buffer_object
*
+ * @base: drm_gem_object superclass data.
* @bdev: Pointer to the buffer object device structure.
* @type: The bo type.
* @destroy: Destruction function. If NULL, kfree is used.
* @num_pages: Actual number of pages.
* @acc_size: Accounted size for this object.
* @kref: Reference count of this buffer object. When this refcount reaches
- * zero, the object is put on the delayed delete list.
- * @list_kref: List reference count of this buffer object. This member is
- * used to avoid destruction while the buffer object is still on a list.
- * Lru lists may keep one refcount, the delayed delete list, and kref != 0
- * keeps one refcount. When this refcount reaches zero,
- * the object is destroyed.
+ * zero, the object is destroyed or put on the delayed delete list.
* @mem: structure describing current placement.
* @persistent_swap_storage: Usually the swap storage is deleted for buffers
* pinned in physical memory. If this behaviour is not desired, this member
* holds a pointer to a persistent shmem object.
* @ttm: TTM structure holding system pages.
* @evicted: Whether the object was evicted without user-space knowing.
- * @cpu_writes: For synchronization. Number of cpu writers.
+ * @deleted: True if the object is only a zombie and already deleted.
* @lru: List head for the lru list.
* @ddestroy: List head for the delayed destroy list.
* @swap: List head for swap LRU list.
* @moving: Fence set when BO is moving
- * @vma_node: Address space manager node.
* @offset: The current GPU offset, which can have different meanings
* depending on the memory type. For SYSTEM type memory, it should be 0.
* @cur_placement: Hint of current placement.
- * @wu_mutex: Wait unreserved mutex.
*
* Base class for TTM buffer object, that deals with data placement and CPU
* mappings. GPU mappings are really up to the driver, but for simpler GPUs
@@ -168,7 +167,7 @@ struct ttm_tt;
*/
struct ttm_buffer_object {
- struct uvm_object uobj;
+ struct drm_gem_object base;
/**
* Members constant at init.
@@ -183,9 +182,7 @@ struct ttm_buffer_object {
/**
* Members not needing protection.
*/
-
struct kref kref;
- struct kref list_kref;
/**
* Members protected by the bo::resv::reserved lock.
@@ -195,12 +192,7 @@ struct ttm_buffer_object {
struct uvm_object *persistent_swap_storage;
struct ttm_tt *ttm;
bool evicted;
-
- /**
- * Members protected by the bo::reserved lock only when written to.
- */
-
- atomic_t cpu_writers;
+ bool deleted;
/**
* Members protected by the bdev::lru_lock.
@@ -216,9 +208,6 @@ struct ttm_buffer_object {
*/
struct dma_fence *moving;
-
- struct drm_vma_offset_node vma_node;
-
unsigned priority;
/**
@@ -230,10 +219,6 @@ struct ttm_buffer_object {
uint64_t offset; /* GPU address space is independent of CPU word size */
struct sg_table *sg;
-
- struct reservation_object *resv;
- struct reservation_object ttm_resv;
- struct rwlock wu_mutex;
};
/**
@@ -276,7 +261,7 @@ struct ttm_bo_kmap_obj {
struct ttm_operation_ctx {
bool interruptible;
bool no_wait_gpu;
- struct reservation_object *resv;
+ struct dma_resv *resv;
uint64_t bytes_moved;
uint32_t flags;
};
@@ -297,19 +282,20 @@ static inline void ttm_bo_get(struct ttm_buffer_object *bo)
}
/**
- * ttm_bo_reference - reference a struct ttm_buffer_object
- *
+ * ttm_bo_get_unless_zero - reference a struct ttm_buffer_object unless
+ * its refcount has already reached zero.
* @bo: The buffer object.
*
- * Returns a refcounted pointer to a buffer object.
+ * Used to reference a TTM buffer object in lookups where the object is removed
+ * from the lookup structure during the destructor and for RCU lookups.
*
- * This function is deprecated. Use @ttm_bo_get instead.
+ * Returns: @bo if the referencing was successful, NULL otherwise.
*/
-
-static inline struct ttm_buffer_object *
-ttm_bo_reference(struct ttm_buffer_object *bo)
+static inline __must_check struct ttm_buffer_object *
+ttm_bo_get_unless_zero(struct ttm_buffer_object *bo)
{
- ttm_bo_get(bo);
+ if (!kref_get_unless_zero(&bo->kref))
+ return NULL;
return bo;
}
@@ -370,50 +356,27 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
void ttm_bo_put(struct ttm_buffer_object *bo);
/**
- * ttm_bo_unref
- *
- * @bo: The buffer object.
- *
- * Unreference and clear a pointer to a buffer object.
- *
- * This function is deprecated. Use @ttm_bo_put instead.
- */
-void ttm_bo_unref(struct ttm_buffer_object **bo);
-
-/**
- * ttm_bo_add_to_lru
- *
- * @bo: The buffer object.
- *
- * Add this bo to the relevant mem type lru and, if it's backed by
- * system pages (ttms) to the swap list.
- * This function must be called with struct ttm_bo_global::lru_lock held, and
- * is typically called immediately prior to unreserving a bo.
- */
-void ttm_bo_add_to_lru(struct ttm_buffer_object *bo);
-
-/**
- * ttm_bo_del_from_lru
+ * ttm_bo_move_to_lru_tail
*
* @bo: The buffer object.
+ * @bulk: optional bulk move structure to remember BO positions
*
- * Remove this bo from all lru lists used to lookup and reserve an object.
- * This function must be called with struct ttm_bo_global::lru_lock held,
- * and is usually called just immediately after the bo has been reserved to
- * avoid recursive reservation from lru lists.
+ * Move this BO to the tail of all lru lists used to lookup and reserve an
+ * object. This function must be called with struct ttm_bo_global::lru_lock
+ * held, and is used to make a BO less likely to be considered for eviction.
*/
-void ttm_bo_del_from_lru(struct ttm_buffer_object *bo);
+void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo,
+ struct ttm_lru_bulk_move *bulk);
/**
- * ttm_bo_move_to_lru_tail
+ * ttm_bo_bulk_move_lru_tail
*
- * @bo: The buffer object.
+ * @bulk: bulk move structure
*
- * Move this BO to the tail of all lru lists used to lookup and reserve an
- * object. This function must be called with struct ttm_bo_global::lru_lock
- * held, and is used to make a BO less likely to be considered for eviction.
+ * Bulk move BOs to the LRU tail, only valid to use when driver makes sure that
+ * BO order never changes. Should be called with ttm_bo_global::lru_lock held.
*/
-void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo);
+void ttm_bo_bulk_move_lru_tail(struct ttm_lru_bulk_move *bulk);
/**
* ttm_bo_lock_delayed_workqueue
@@ -443,31 +406,6 @@ bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
const struct ttm_place *place);
/**
- * ttm_bo_synccpu_write_grab
- *
- * @bo: The buffer object:
- * @no_wait: Return immediately if buffer is busy.
- *
- * Synchronizes a buffer object for CPU RW access. This means
- * command submission that affects the buffer will return -EBUSY
- * until ttm_bo_synccpu_write_release is called.
- *
- * Returns
- * -EBUSY if the buffer is busy and no_wait is true.
- * -ERESTARTSYS if interrupted by a signal.
- */
-int ttm_bo_synccpu_write_grab(struct ttm_buffer_object *bo, bool no_wait);
-
-/**
- * ttm_bo_synccpu_write_release:
- *
- * @bo : The buffer object.
- *
- * Releases a synccpu lock.
- */
-void ttm_bo_synccpu_write_release(struct ttm_buffer_object *bo);
-
-/**
* ttm_bo_acc_size
*
* @bdev: Pointer to a ttm_bo_device struct.
@@ -494,7 +432,7 @@ size_t ttm_bo_dma_acc_size(struct ttm_bo_device *bdev,
* @page_alignment: Data alignment in pages.
* @ctx: TTM operation context for memory allocation.
* @acc_size: Accounted size for this object.
- * @resv: Pointer to a reservation_object, or NULL to let ttm allocate one.
+ * @resv: Pointer to a dma_resv, or NULL to let ttm allocate one.
* @destroy: Destroy function. Use NULL for kfree().
*
* This function initializes a pre-allocated struct ttm_buffer_object.
@@ -527,7 +465,7 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev,
struct ttm_operation_ctx *ctx,
size_t acc_size,
struct sg_table *sg,
- struct reservation_object *resv,
+ struct dma_resv *resv,
void (*destroy) (struct ttm_buffer_object *));
/**
@@ -546,7 +484,7 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev,
* point to the shmem object backing a GEM object if TTM is used to back a
* GEM user interface.
* @acc_size: Accounted size for this object.
- * @resv: Pointer to a reservation_object, or NULL to let ttm allocate one.
+ * @resv: Pointer to a dma_resv, or NULL to let ttm allocate one.
* @destroy: Destroy function. Use NULL for kfree().
*
* This function initializes a pre-allocated struct ttm_buffer_object.
@@ -571,7 +509,7 @@ int ttm_bo_init(struct ttm_bo_device *bdev, struct ttm_buffer_object *bo,
unsigned long size, enum ttm_bo_type type,
struct ttm_placement *placement,
uint32_t page_alignment, bool interrubtible, size_t acc_size,
- struct sg_table *sg, struct reservation_object *resv,
+ struct sg_table *sg, struct dma_resv *resv,
void (*destroy) (struct ttm_buffer_object *));
/**
@@ -712,16 +650,14 @@ void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map);
#ifdef notyet
/**
- * ttm_fbdev_mmap - mmap fbdev memory backed by a ttm buffer object.
+ * ttm_bo_mmap_obj - mmap memory backed by a ttm buffer object.
*
* @vma: vma as input from the fbdev mmap method.
- * @bo: The bo backing the address space. The address space will
- * have the same size as the bo, and start at offset 0.
+ * @bo: The bo backing the address space.
*
- * This function is intended to be called by the fbdev mmap method
- * if the fbdev address space is to be backed by a bo.
+ * Maps a buffer object.
*/
-int ttm_fbdev_mmap(struct vm_area_struct *vma, struct ttm_buffer_object *bo);
+int ttm_bo_mmap_obj(struct vm_area_struct *vma, struct ttm_buffer_object *bo);
/**
* ttm_bo_mmap - mmap out of the ttm device address space.
@@ -735,14 +671,15 @@ int ttm_fbdev_mmap(struct vm_area_struct *vma, struct ttm_buffer_object *bo);
*/
int ttm_bo_mmap(struct file *filp, struct vm_area_struct *vma,
struct ttm_bo_device *bdev);
+#else
+struct uvm_object *ttm_bo_mmap(struct file *, voff_t, vsize_t,
+ struct ttm_bo_device *);
#endif
void *ttm_kmap_atomic_prot(struct vm_page *page, pgprot_t prot);
void ttm_kunmap_atomic_prot(void *addr, pgprot_t prot);
-extern struct uvm_object *ttm_bo_mmap(voff_t, vsize_t, struct ttm_bo_device *);
-
/**
* ttm_bo_io
*
@@ -770,5 +707,49 @@ ssize_t ttm_bo_io(struct ttm_bo_device *bdev, struct file *filp,
int ttm_bo_swapout(struct ttm_bo_global *glob,
struct ttm_operation_ctx *ctx);
void ttm_bo_swapout_all(struct ttm_bo_device *bdev);
-int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo);
+
+/**
+ * ttm_bo_uses_embedded_gem_object - check if the given bo uses the
+ * embedded drm_gem_object.
+ *
+ * Most ttm drivers are using gem too, so the embedded
+ * ttm_buffer_object.base will be initialized by the driver (before
+ * calling ttm_bo_init). It is also possible to use ttm without gem
+ * though (vmwgfx does that).
+ *
+ * This helper will figure whenever a given ttm bo is a gem object too
+ * or not.
+ *
+ * @bo: The bo to check.
+ */
+static inline bool ttm_bo_uses_embedded_gem_object(struct ttm_buffer_object *bo)
+{
+ return bo->base.dev != NULL;
+}
+
+/* Default number of pre-faulted pages in the TTM fault handler */
+#define TTM_BO_VM_NUM_PREFAULT 16
+
+#ifdef __linux__
+vm_fault_t ttm_bo_vm_reserve(struct ttm_buffer_object *bo,
+ struct vm_fault *vmf);
+
+vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf,
+ pgprot_t prot,
+ pgoff_t num_prefault,
+ pgoff_t fault_page_size);
+
+vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf);
+
+void ttm_bo_vm_open(struct vm_area_struct *vma);
+
+void ttm_bo_vm_close(struct vm_area_struct *vma);
+
+int ttm_bo_vm_access(struct vm_area_struct *vma, unsigned long addr,
+ void *buf, int len, int write);
+#else
+int ttm_bo_vm_fault(struct uvm_faultinfo *, vaddr_t, vm_page_t *,
+ int, int, vm_fault_t, vm_prot_t, int);
+#endif /* !__linux__ */
+
#endif
diff --git a/sys/dev/pci/drm/include/drm/ttm/ttm_bo_driver.h b/sys/dev/pci/drm/include/drm/ttm/ttm_bo_driver.h
index dfb60677965..4e4df19a8a9 100644
--- a/sys/dev/pci/drm/include/drm/ttm/ttm_bo_driver.h
+++ b/sys/dev/pci/drm/include/drm/ttm/ttm_bo_driver.h
@@ -31,13 +31,11 @@
#define _TTM_BO_DRIVER_H_
#include <drm/drm_mm.h>
-#include <drm/drm_global.h>
#include <drm/drm_vma_manager.h>
-#include <drm/drm_print.h>
#include <linux/workqueue.h>
#include <linux/fs.h>
#include <linux/spinlock.h>
-#include <linux/reservation.h>
+#include <linux/dma-resv.h>
#include "ttm_bo_api.h"
#include "ttm_memory.h"
@@ -212,8 +210,6 @@ struct ttm_mem_type_manager {
* struct ttm_bo_driver
*
* @create_ttm_backend_entry: Callback to create a struct ttm_backend.
- * @invalidate_caches: Callback to invalidate read caches when a buffer object
- * has been evicted.
* @init_mem_type: Callback to initialize a struct ttm_mem_type_manager
* structure.
* @evict_flags: Callback to obtain placement flags when a buffer is evicted.
@@ -258,19 +254,6 @@ struct ttm_bo_driver {
*/
void (*ttm_tt_unpopulate)(struct ttm_tt *ttm);
- /**
- * struct ttm_bo_driver member invalidate_caches
- *
- * @bdev: the buffer object device.
- * @flags: new placement of the rebound buffer object.
- *
- * A previosly evicted buffer has been rebound in a
- * potentially new location. Tell the driver that it might
- * consider invalidating read (texture) caches on the next command
- * submission as a consequence.
- */
-
- int (*invalidate_caches)(struct ttm_bo_device *bdev, uint32_t flags);
int (*init_mem_type)(struct ttm_bo_device *bdev, uint32_t type,
struct ttm_mem_type_manager *man);
@@ -383,15 +366,25 @@ struct ttm_bo_driver {
*/
int (*access_memory)(struct ttm_buffer_object *bo, unsigned long offset,
void *buf, int len, int write);
-};
-/**
- * struct ttm_bo_global_ref - Argument to initialize a struct ttm_bo_global.
- */
+ /**
+ * struct ttm_bo_driver member del_from_lru_notify
+ *
+ * @bo: the buffer object deleted from lru
+ *
+ * notify driver that a BO was deleted from LRU.
+ */
+ void (*del_from_lru_notify)(struct ttm_buffer_object *bo);
-struct ttm_bo_global_ref {
- struct drm_global_reference ref;
- struct ttm_mem_global *mem_glob;
+ /**
+ * Notify the driver that we're about to release a BO
+ *
+ * @bo: BO that is about to be released
+ *
+ * Gives the driver a chance to do any cleanup, including
+ * adding fences that may force a delayed delete
+ */
+ void (*release_notify)(struct ttm_buffer_object *bo);
};
/**
@@ -408,20 +401,18 @@ struct ttm_bo_global_ref {
* @swap_lru: Lru list of buffer objects used for swapping.
*/
-struct ttm_bo_global {
+extern struct ttm_bo_global {
/**
* Constant after init.
*/
struct kobject kobj;
- struct ttm_mem_global *mem_glob;
struct vm_page *dummy_read_page;
- struct rwlock device_list_mutex;
spinlock_t lru_lock;
/**
- * Protected by device_list_mutex.
+ * Protected by ttm_global_mutex.
*/
struct list_head device_list;
@@ -434,7 +425,7 @@ struct ttm_bo_global {
* Internal protection.
*/
atomic_t bo_count;
-};
+} ttm_bo_glob;
#define TTM_NUM_MEM_TYPES 8
@@ -444,7 +435,7 @@ struct ttm_bo_global {
*
* @driver: Pointer to a struct ttm_bo_driver struct setup by the driver.
* @man: An array of mem_type_managers.
- * @vma_manager: Address space manager
+ * @vma_manager: Address space manager (pointer)
* lru_lock: Spinlock that protects the buffer+device lru lists and
* ddestroy lists.
* @dev_mapping: A pointer to the struct address_space representing the
@@ -460,7 +451,6 @@ struct ttm_bo_device {
* Constant after bo device init / atomic.
*/
struct list_head device_list;
- struct ttm_bo_global *glob;
struct ttm_bo_driver *driver;
struct ttm_mem_type_manager man[TTM_NUM_MEM_TYPES];
@@ -471,7 +461,7 @@ struct ttm_bo_device {
/*
* Protected by internal locks.
*/
- struct drm_vma_offset_manager vma_manager;
+ struct drm_vma_offset_manager *vma_manager;
/*
* Protected by the global:lru lock.
@@ -496,6 +486,34 @@ struct ttm_bo_device {
};
/**
+ * struct ttm_lru_bulk_move_pos
+ *
+ * @first: first BO in the bulk move range
+ * @last: last BO in the bulk move range
+ *
+ * Positions for a lru bulk move.
+ */
+struct ttm_lru_bulk_move_pos {
+ struct ttm_buffer_object *first;
+ struct ttm_buffer_object *last;
+};
+
+/**
+ * struct ttm_lru_bulk_move
+ *
+ * @tt: first/last lru entry for BOs in the TT domain
+ * @vram: first/last lru entry for BOs in the VRAM domain
+ * @swap: first/last lru entry for BOs on the swap list
+ *
+ * Helper structure for bulk moves on the LRU list.
+ */
+struct ttm_lru_bulk_move {
+ struct ttm_lru_bulk_move_pos tt[TTM_MAX_BO_PRIORITY];
+ struct ttm_lru_bulk_move_pos vram[TTM_MAX_BO_PRIORITY];
+ struct ttm_lru_bulk_move_pos swap[TTM_MAX_BO_PRIORITY];
+};
+
+/**
* ttm_flag_masked
*
* @old: Pointer to the result and original value.
@@ -555,9 +573,6 @@ void ttm_bo_mem_put(struct ttm_buffer_object *bo, struct ttm_mem_reg *mem);
void ttm_bo_mem_put_locked(struct ttm_buffer_object *bo,
struct ttm_mem_reg *mem);
-void ttm_bo_global_release(struct drm_global_reference *ref);
-int ttm_bo_global_init(struct drm_global_reference *ref);
-
int ttm_bo_device_release(struct ttm_bo_device *bdev);
/**
@@ -567,6 +582,7 @@ int ttm_bo_device_release(struct ttm_bo_device *bdev);
* @glob: A pointer to an initialized struct ttm_bo_global.
* @driver: A pointer to a struct ttm_bo_driver set up by the caller.
* @mapping: The address space to use for this bo.
+ * @vma_manager: A pointer to a vma manager.
* @file_page_offset: Offset into the device address space that is available
* for buffer data. This ensures compatibility with other users of the
* address space.
@@ -575,10 +591,11 @@ int ttm_bo_device_release(struct ttm_bo_device *bdev);
* Returns:
* !0: Failure.
*/
-int ttm_bo_device_init(struct ttm_bo_device *bdev, struct ttm_bo_global *glob,
+int ttm_bo_device_init(struct ttm_bo_device *bdev,
struct ttm_bo_driver *driver,
struct address_space *mapping,
- uint64_t file_page_offset, bool need_dma32);
+ struct drm_vma_offset_manager *vma_manager,
+ bool need_dma32);
/**
* ttm_bo_unmap_virtual
@@ -601,9 +618,6 @@ void ttm_mem_io_free_vm(struct ttm_buffer_object *bo);
int ttm_mem_io_lock(struct ttm_mem_type_manager *man, bool interruptible);
void ttm_mem_io_unlock(struct ttm_mem_type_manager *man);
-void ttm_bo_del_sub_from_lru(struct ttm_buffer_object *bo);
-void ttm_bo_add_to_lru(struct ttm_buffer_object *bo);
-
/**
* __ttm_bo_reserve:
*
@@ -636,14 +650,14 @@ static inline int __ttm_bo_reserve(struct ttm_buffer_object *bo,
if (WARN_ON(ticket))
return -EBUSY;
- success = reservation_object_trylock(bo->resv);
+ success = dma_resv_trylock(bo->base.resv);
return success ? 0 : -EBUSY;
}
if (interruptible)
- ret = reservation_object_lock_interruptible(bo->resv, ticket);
+ ret = dma_resv_lock_interruptible(bo->base.resv, ticket);
else
- ret = reservation_object_lock(bo->resv, ticket);
+ ret = dma_resv_lock(bo->base.resv, ticket);
if (ret == -EINTR)
return -ERESTARTSYS;
return ret;
@@ -697,15 +711,9 @@ static inline int ttm_bo_reserve(struct ttm_buffer_object *bo,
bool interruptible, bool no_wait,
struct ww_acquire_ctx *ticket)
{
- int ret;
-
WARN_ON(!kref_read(&bo->kref));
- ret = __ttm_bo_reserve(bo, interruptible, no_wait, ticket);
- if (likely(ret == 0))
- ttm_bo_del_sub_from_lru(bo);
-
- return ret;
+ return __ttm_bo_reserve(bo, interruptible, no_wait, ticket);
}
/**
@@ -727,14 +735,12 @@ static inline int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo,
WARN_ON(!kref_read(&bo->kref));
if (interruptible)
- ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock,
- ticket);
+ ret = dma_resv_lock_slow_interruptible(bo->base.resv,
+ ticket);
else
- ww_mutex_lock_slow(&bo->resv->lock, ticket);
+ dma_resv_lock_slow(bo->base.resv, ticket);
- if (likely(ret == 0))
- ttm_bo_del_sub_from_lru(bo);
- else if (ret == -EINTR)
+ if (ret == -EINTR)
ret = -ERESTARTSYS;
return ret;
@@ -749,12 +755,10 @@ static inline int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo,
*/
static inline void ttm_bo_unreserve(struct ttm_buffer_object *bo)
{
- if (!(bo->mem.placement & TTM_PL_FLAG_NO_EVICT)) {
- spin_lock(&bo->bdev->glob->lru_lock);
- ttm_bo_add_to_lru(bo);
- spin_unlock(&bo->bdev->glob->lru_lock);
- }
- reservation_object_unlock(bo->resv);
+ spin_lock(&ttm_bo_glob.lru_lock);
+ ttm_bo_move_to_lru_tail(bo, NULL);
+ spin_unlock(&ttm_bo_glob.lru_lock);
+ dma_resv_unlock(bo->base.resv);
}
/*
@@ -857,7 +861,7 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo,
*
* @bo: A pointer to a struct ttm_buffer_object.
*
- * Pipelined gutting a BO of it's backing store.
+ * Pipelined gutting a BO of its backing store.
*/
int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo);
diff --git a/sys/dev/pci/drm/include/drm/ttm/ttm_execbuf_util.h b/sys/dev/pci/drm/include/drm/ttm/ttm_execbuf_util.h
index b0fdd198003..5a19843bb80 100644
--- a/sys/dev/pci/drm/include/drm/ttm/ttm_execbuf_util.h
+++ b/sys/dev/pci/drm/include/drm/ttm/ttm_execbuf_util.h
@@ -40,13 +40,13 @@
*
* @head: list head for thread-private list.
* @bo: refcounted buffer object pointer.
- * @shared: should the fence be added shared?
+ * @num_shared: How many shared fences we want to add.
*/
struct ttm_validate_buffer {
struct list_head head;
struct ttm_buffer_object *bo;
- bool shared;
+ unsigned int num_shared;
};
/**
@@ -70,6 +70,7 @@ extern void ttm_eu_backoff_reservation(struct ww_acquire_ctx *ticket,
* @list: thread private list of ttm_validate_buffer structs.
* @intr: should the wait be interruptible
* @dups: [out] optional list of duplicates.
+ * @del_lru: true if BOs should be removed from the LRU.
*
* Tries to reserve bos pointed to by the list entries for validation.
* If the function returns 0, all buffers are marked as "unfenced",
diff --git a/sys/dev/pci/drm/include/drm/ttm/ttm_memory.h b/sys/dev/pci/drm/include/drm/ttm/ttm_memory.h
index 43c97fb01fb..3f98db6375e 100644
--- a/sys/dev/pci/drm/include/drm/ttm/ttm_memory.h
+++ b/sys/dev/pci/drm/include/drm/ttm/ttm_memory.h
@@ -63,9 +63,8 @@
#define TTM_MEM_MAX_ZONES 2
struct ttm_mem_zone;
-struct ttm_mem_global {
+extern struct ttm_mem_global {
struct kobject kobj;
- struct ttm_bo_global *bo_glob;
struct workqueue_struct *swap_queue;
struct work_struct work;
spinlock_t lock;
@@ -78,7 +77,7 @@ struct ttm_mem_global {
#else
struct ttm_mem_zone *zone_dma32;
#endif
-};
+} ttm_mem_glob;
extern int ttm_mem_global_init(struct ttm_mem_global *glob);
extern void ttm_mem_global_release(struct ttm_mem_global *glob);
diff --git a/sys/dev/pci/drm/include/drm/ttm/ttm_page_alloc.h b/sys/dev/pci/drm/include/drm/ttm/ttm_page_alloc.h
index 4d9b019d253..a6b6ef5f9bf 100644
--- a/sys/dev/pci/drm/include/drm/ttm/ttm_page_alloc.h
+++ b/sys/dev/pci/drm/include/drm/ttm/ttm_page_alloc.h
@@ -74,7 +74,7 @@ void ttm_unmap_and_unpopulate_pages(struct device *dev, struct ttm_dma_tt *tt);
*/
int ttm_page_alloc_debugfs(struct seq_file *m, void *data);
-#if defined(CONFIG_SWIOTLB) || defined(CONFIG_INTEL_IOMMU)
+#if defined(CONFIG_DRM_TTM_DMA_PAGE_POOL)
/**
* Initialize pool allocator.
*/
diff --git a/sys/dev/pci/drm/include/drm/ttm/ttm_set_memory.h b/sys/dev/pci/drm/include/drm/ttm/ttm_set_memory.h
index 035fc418152..0209935fdc6 100644
--- a/sys/dev/pci/drm/include/drm/ttm/ttm_set_memory.h
+++ b/sys/dev/pci/drm/include/drm/ttm/ttm_set_memory.h
@@ -37,7 +37,6 @@
#include <asm/set_memory.h>
-
static inline int ttm_set_pages_array_wb(struct vm_page **pages, int addrinarray)
{
return set_pages_array_wb(pages, addrinarray);
diff --git a/sys/dev/pci/drm/include/drm/ttm/ttm_tt.h b/sys/dev/pci/drm/include/drm/ttm/ttm_tt.h
index 0aa65fa1a21..adb52b17962 100644
--- a/sys/dev/pci/drm/include/drm/ttm/ttm_tt.h
+++ b/sys/dev/pci/drm/include/drm/ttm/ttm_tt.h
@@ -28,7 +28,6 @@
#define _TTM_TT_H_
#include <linux/types.h>
-#include <drm/drmP.h>
struct ttm_tt;
struct ttm_mem_reg;
@@ -253,6 +252,7 @@ int ttm_tt_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx);
void ttm_tt_unpopulate(struct ttm_tt *ttm);
#if IS_ENABLED(CONFIG_AGP)
+#include <linux/agp_backend.h>
/**
* ttm_agp_tt_create
diff --git a/sys/dev/pci/drm/include/generated/autoconf.h b/sys/dev/pci/drm/include/generated/autoconf.h
index be8d046c856..05af433246b 100644
--- a/sys/dev/pci/drm/include/generated/autoconf.h
+++ b/sys/dev/pci/drm/include/generated/autoconf.h
@@ -4,24 +4,25 @@
#define CONFIG_BACKLIGHT_CLASS_DEVICE 1
#define CONFIG_DRM_FBDEV_EMULATION 1
-#define CONFIG_DRM_FBDEV_OVERALLOC 0
-#define CONFIG_DRM_I915_DEBUG 0
-#define CONFIG_DRM_I915_DEBUG_GEM 0
+#define CONFIG_DRM_PANEL 1
#define CONFIG_DRM_I915_FBDEV 1
-#define CONFIG_DRM_I915_ALPHA_SUPPORT 0
#define CONFIG_DRM_I915_CAPTURE_ERROR 1
-#define CONFIG_DRM_I915_GVT 0
-#define CONFIG_DRM_I915_SW_FENCE_CHECK_DAG 0
-#define CONFIG_PM 0
#define CONFIG_DRM_AMD_DC 1
#if defined(__amd64__) || defined(__i386__)
-#define CONFIG_DRM_AMD_DC_DCN1_0 1
+#define CONFIG_DRM_AMD_DC_DCN 1
#endif
#if 0
#define CONFIG_DRM_AMDGPU_CIK 1
#define CONFIG_DRM_AMDGPU_SI 1
#endif
+#define CONFIG_DRM_I915_PREEMPT_TIMEOUT 640 /* ms */
+#define CONFIG_DRM_I915_TIMESLICE_DURATION 1 /* ms */
+#define CONFIG_DRM_I915_HEARTBEAT_INTERVAL 2500 /* ms */
+#define CONFIG_DRM_I915_MAX_REQUEST_BUSYWAIT 8000 /* ns */
+#define CONFIG_DRM_I915_STOP_TIMEOUT 100 /* ms */
+#define CONFIG_DRM_I915_FORCE_PROBE ""
+
#ifdef __HAVE_ACPI
#include "acpi.h"
#if NACPI > 0
@@ -29,6 +30,11 @@
#endif
#endif
+#include "pci.h"
+#if NPCI > 0
+#define CONFIG_PCI 1
+#endif
+
#include "agp.h"
#if NAGP > 0
#define CONFIG_AGP 1
@@ -49,3 +55,29 @@
#define CONFIG_X86_32 1
#define CONFIG_X86_PAT 1
#endif
+
+#ifdef __arm__
+#define CONFIG_ARM 1
+#endif
+
+#ifdef __arm64__
+#define CONFIG_ARM64 1
+#endif
+
+#ifdef __macppc__
+#define CONFIG_PPC 1
+#define CONFIG_PPC_PMAC 1
+#endif
+
+#ifdef __powerpc64__
+#define CONFIG_PPC64 1
+#endif
+
+#ifdef __loongson__
+#define CONFIG_MIPS 1
+#define CONFIG_CPU_LOONGSON64 1
+#endif
+
+#ifdef __LP64__
+#define CONFIG_64BIT 1
+#endif
diff --git a/sys/dev/pci/drm/include/linux/agp_backend.h b/sys/dev/pci/drm/include/linux/agp_backend.h
index 452d8e92834..c3f937853a9 100644
--- a/sys/dev/pci/drm/include/linux/agp_backend.h
+++ b/sys/dev/pci/drm/include/linux/agp_backend.h
@@ -10,4 +10,6 @@
#define AGP_USER_CACHED_MEMORY BUS_DMA_COHERENT
#endif
+struct drm_agp_head;
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/ascii85.h b/sys/dev/pci/drm/include/linux/ascii85.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/ascii85.h
diff --git a/sys/dev/pci/drm/include/linux/atomic.h b/sys/dev/pci/drm/include/linux/atomic.h
index 5e23da1490e..bb43b294c4c 100644
--- a/sys/dev/pci/drm/include/linux/atomic.h
+++ b/sys/dev/pci/drm/include/linux/atomic.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: atomic.h,v 1.5 2019/08/17 06:07:22 jsg Exp $ */
+/* $OpenBSD: atomic.h,v 1.6 2020/06/08 04:48:14 jsg Exp $ */
/**
* \file drm_atomic.h
* Atomic operations used in the DRM which may or may not be provided by the OS.
@@ -36,8 +36,10 @@
#include <sys/types.h>
#include <sys/mutex.h>
#include <machine/intr.h>
-#include <machine/atomic.h>
#include <linux/types.h>
+#include <linux/compiler.h> /* via x86/include/asm/atomic.h */
+
+#define ATOMIC_INIT(x) (x)
#define atomic_set(p, v) (*(p) = (v))
#define atomic_read(p) (*(p))
@@ -45,17 +47,34 @@
#define atomic_dec(p) __sync_fetch_and_sub(p, 1)
#define atomic_add(n, p) __sync_fetch_and_add(p, n)
#define atomic_sub(n, p) __sync_fetch_and_sub(p, n)
+#define atomic_and(n, p) __sync_fetch_and_and(p, n)
+#define atomic_or(n, p) atomic_setbits_int(p, n)
#define atomic_add_return(n, p) __sync_add_and_fetch(p, n)
#define atomic_sub_return(n, p) __sync_sub_and_fetch(p, n)
#define atomic_inc_return(v) atomic_add_return(1, (v))
#define atomic_dec_return(v) atomic_sub_return(1, (v))
#define atomic_dec_and_test(v) (atomic_dec_return(v) == 0)
#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
-#define atomic_or(n, p) atomic_setbits_int(p, n)
#define atomic_cmpxchg(p, o, n) __sync_val_compare_and_swap(p, o, n)
#define cmpxchg(p, o, n) __sync_val_compare_and_swap(p, o, n)
#define atomic_set_release(p, v) atomic_set((p), (v))
+#define try_cmpxchg(p, op, n) \
+({ \
+ __typeof(p) __op = (__typeof((p)))(op); \
+ __typeof(*(p)) __o = *__op; \
+ __typeof(*(p)) __p = __sync_val_compare_and_swap((p), (__o), (n)); \
+ if (__p != __o) \
+ *__op = __p; \
+ (__p == __o); \
+})
+
+static inline bool
+atomic_try_cmpxchg(volatile int *p, int *op, int n)
+{
+ return try_cmpxchg(p, op, n);
+}
+
static inline int
atomic_xchg(volatile int *v, int n)
{
@@ -99,6 +118,8 @@ atomic_dec_if_positive(volatile int *v)
#ifdef __LP64__
typedef int64_t atomic64_t;
+#define ATOMIC64_INIT(x) (x)
+
#define atomic64_set(p, v) (*(p) = (v))
#define atomic64_read(p) (*(p))
@@ -122,6 +143,8 @@ typedef struct {
struct mutex lock;
} atomic64_t;
+#define ATOMIC64_INIT(x) { (x), .lock = MUTEX_INITIALIZER(IPL_HIGH) }
+
static inline void
atomic64_set(atomic64_t *v, int64_t i)
{
@@ -236,6 +259,13 @@ clear_bit(u_int b, volatile void *p)
}
static inline void
+clear_bit_unlock(u_int b, volatile void *p)
+{
+ membar_enter();
+ clear_bit(b, p);
+}
+
+static inline void
set_bit(u_int b, volatile void *p)
{
atomic_set_int(((volatile u_int *)p) + (b >> 5), 1 << (b & 0x1f));
diff --git a/sys/dev/pci/drm/include/linux/average.h b/sys/dev/pci/drm/include/linux/average.h
new file mode 100644
index 00000000000..d78c65b78b4
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/average.h
@@ -0,0 +1,38 @@
+/* Public domain. */
+
+#ifndef _LINUX_AVERAGE_H
+#define _LINUX_AVERAGE_H
+
+#include <sys/types.h>
+#include <lib/libkern/libkern.h>
+
+#define DECLARE_EWMA(name, precision, recip) \
+struct ewma_##name { \
+ u_long value; \
+}; \
+ \
+static inline void \
+ewma_##name##_init(struct ewma_##name *p) \
+{ \
+ p->value = 0; \
+} \
+ \
+static inline void \
+ewma_##name##_add(struct ewma_##name *p, u_long value) \
+{ \
+ u_long shift = fls(recip) - 1; \
+ \
+ if (p->value == 0) \
+ p->value = (value << (precision)); \
+ else \
+ p->value = ((((p->value << shift) - p->value) + \
+ (value << (precision))) >> shift); \
+} \
+ \
+static inline u_long \
+ewma_##name##_read(struct ewma_##name *p) \
+{ \
+ return (p->value >> (precision)); \
+}
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/backlight.h b/sys/dev/pci/drm/include/linux/backlight.h
index fa559dbe047..cfcec3220e9 100644
--- a/sys/dev/pci/drm/include/linux/backlight.h
+++ b/sys/dev/pci/drm/include/linux/backlight.h
@@ -54,4 +54,9 @@ backlight_force_update(struct backlight_device *bd, int reason)
void backlight_schedule_update_status(struct backlight_device *);
+int backlight_enable(struct backlight_device *);
+int backlight_disable(struct backlight_device *);
+
+#define devm_of_find_backlight(x) NULL
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/bitfield.h b/sys/dev/pci/drm/include/linux/bitfield.h
new file mode 100644
index 00000000000..909ddaa8bac
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/bitfield.h
@@ -0,0 +1,16 @@
+/* Public domain. */
+
+#ifndef _LINUX_BITFIELD_H
+#define _LINUX_BITFIELD_H
+
+#include <asm/byteorder.h>
+
+#define __bf_shf(x) (__builtin_ffsll(x) - 1)
+
+#define FIELD_GET(_m, _v) \
+ ((typeof(_m))(((_v) & (_m)) >> __bf_shf(_m)))
+
+#define FIELD_PREP(_m, _v) \
+ (((typeof(_m))(_v) << __bf_shf(_m)) & (_m))
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/bitmap.h b/sys/dev/pci/drm/include/linux/bitmap.h
index dc2055db5d2..c3160639a75 100644
--- a/sys/dev/pci/drm/include/linux/bitmap.h
+++ b/sys/dev/pci/drm/include/linux/bitmap.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bitmap.h,v 1.2 2019/07/11 04:26:37 jsg Exp $ */
+/* $OpenBSD: bitmap.h,v 1.3 2020/06/08 04:48:14 jsg Exp $ */
/*
* Copyright (c) 2013, 2014, 2015 Mark Kettenis
*
@@ -64,6 +64,18 @@ bitmap_or(void *d, void *s1, void *s2, u_int n)
}
static inline void
+bitmap_andnot(void *d, void *s1, void *s2, u_int n)
+{
+ u_int *dst = d;
+ u_int *src1 = s1;
+ u_int *src2 = s2;
+ u_int b;
+
+ for (b = 0; b < n; b += 32)
+ dst[b >> 5] = src1[b >> 5] & ~src2[b >> 5];
+}
+
+static inline void
bitmap_complement(void *d, void *s, u_int n)
{
u_int *dst = d;
@@ -74,6 +86,17 @@ bitmap_complement(void *d, void *s, u_int n)
dst[b >> 5] = ~src[b >> 5];
}
+static inline void
+bitmap_copy(void *d, void *s, u_int n)
+{
+ u_int *dst = d;
+ u_int *src = s;
+ u_int b;
+
+ for (b = 0; b < n; b += 32)
+ dst[b >> 5] = src[b >> 5];
+}
+
static inline int
bitmap_weight(void *p, u_int n)
{
@@ -86,4 +109,7 @@ bitmap_weight(void *p, u_int n)
return sum;
}
+void *bitmap_zalloc(u_int, gfp_t);
+void bitmap_free(void *);
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/bitops.h b/sys/dev/pci/drm/include/linux/bitops.h
index 73317e1791b..72bf3b79590 100644
--- a/sys/dev/pci/drm/include/linux/bitops.h
+++ b/sys/dev/pci/drm/include/linux/bitops.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bitops.h,v 1.2 2019/11/24 02:29:43 jsg Exp $ */
+/* $OpenBSD: bitops.h,v 1.3 2020/06/08 04:48:14 jsg Exp $ */
/*
* Copyright (c) 2013, 2014, 2015 Mark Kettenis
*
@@ -25,13 +25,19 @@
#define BIT(x) (1UL << (x))
#define BIT_ULL(x) (1ULL << (x))
+#define BIT_MASK(x) (1UL << ((x) % BITS_PER_LONG))
#define BITS_PER_BYTE 8
#define GENMASK(h, l) (((~0UL) >> (BITS_PER_LONG - (h) - 1)) & ((~0UL) << (l)))
#define GENMASK_ULL(h, l) (((~0ULL) >> (BITS_PER_LONG_LONG - (h) - 1)) & ((~0ULL) << (l)))
+#define BITS_PER_TYPE(x) (8 * sizeof(x))
#define BITS_TO_LONGS(x) howmany((x), 8 * sizeof(long))
+/* despite the name these are really ctz */
+#define __ffs(x) __builtin_ctzl(x)
+#define __ffs64(x) __builtin_ctzll(x)
+
static inline uint8_t
hweight8(uint32_t x)
{
diff --git a/sys/dev/pci/drm/include/linux/bits.h b/sys/dev/pci/drm/include/linux/bits.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/bits.h
diff --git a/sys/dev/pci/drm/include/linux/bottom_half.h b/sys/dev/pci/drm/include/linux/bottom_half.h
index 1261bf12fe1..9d13c06ac56 100644
--- a/sys/dev/pci/drm/include/linux/bottom_half.h
+++ b/sys/dev/pci/drm/include/linux/bottom_half.h
@@ -3,6 +3,8 @@
#ifndef _LINUX_BOTTOM_HALF_H
#define _LINUX_BOTTOM_HALF_H
+#include <linux/preempt.h>
+
#define local_bh_disable()
#define local_bh_enable()
diff --git a/sys/dev/pci/drm/include/linux/build_bug.h b/sys/dev/pci/drm/include/linux/build_bug.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/build_bug.h
diff --git a/sys/dev/pci/drm/include/linux/byteorder/generic.h b/sys/dev/pci/drm/include/linux/byteorder/generic.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/byteorder/generic.h
diff --git a/sys/dev/pci/drm/include/linux/compiler.h b/sys/dev/pci/drm/include/linux/compiler.h
index c2f09e25afe..6e7c02ddb19 100644
--- a/sys/dev/pci/drm/include/linux/compiler.h
+++ b/sys/dev/pci/drm/include/linux/compiler.h
@@ -4,11 +4,14 @@
#define _LINUX_COMPILER_H
#include <linux/kconfig.h>
+#include <sys/atomic.h> /* for READ_ONCE() WRITE_ONCE() */
#define unlikely(x) __builtin_expect(!!(x), 0)
#define likely(x) __builtin_expect(!!(x), 1)
#define __force
+#define __acquires(x)
+#define __releases(x)
#define __always_unused __unused
#define __maybe_unused
#define __read_mostly
@@ -19,6 +22,7 @@
#define __deprecated
#define __always_inline inline
#define noinline __attribute__((noinline))
+#define fallthrough do {} while (0)
#ifndef __user
#define __user
@@ -30,4 +34,20 @@
#define uninitialized_var(x) x
+/* The Linux code doesn't meet our usual standards! */
+#ifdef __clang__
+#pragma clang diagnostic ignored "-Wenum-conversion"
+#pragma clang diagnostic ignored "-Winitializer-overrides"
+#pragma clang diagnostic ignored "-Wtautological-compare"
+#pragma clang diagnostic ignored "-Wunneeded-internal-declaration"
+#pragma clang diagnostic ignored "-Wunused-const-variable"
+#pragma clang diagnostic ignored "-Wincompatible-pointer-types-discards-qualifiers"
+#pragma clang diagnostic ignored "-Wunused-function"
+#pragma clang diagnostic ignored "-Wunused-variable"
+#pragma clang diagnostic ignored "-Wparentheses-equality"
+#pragma clang diagnostic ignored "-Wmissing-braces"
+#else
+#pragma GCC diagnostic ignored "-Wformat-zero-length"
+#endif
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/completion.h b/sys/dev/pci/drm/include/linux/completion.h
index 0fb61e8c288..f1233514f80 100644
--- a/sys/dev/pci/drm/include/linux/completion.h
+++ b/sys/dev/pci/drm/include/linux/completion.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: completion.h,v 1.3 2019/12/30 09:30:31 mpi Exp $ */
+/* $OpenBSD: completion.h,v 1.4 2020/06/08 04:48:14 jsg Exp $ */
/*
* Copyright (c) 2015, 2018 Mark Kettenis
*
@@ -35,6 +35,12 @@ init_completion(struct completion *x)
mtx_init(&x->wait.lock, IPL_TTY);
}
+static inline void
+reinit_completion(struct completion *x)
+{
+ x->done = 0;
+}
+
static inline u_long
wait_for_completion_timeout(struct completion *x, u_long timo)
{
@@ -57,6 +63,27 @@ wait_for_completion_timeout(struct completion *x, u_long timo)
}
static inline u_long
+wait_for_completion(struct completion *x)
+{
+ int ret;
+
+ KASSERT(!cold);
+
+ mtx_enter(&x->wait.lock);
+ while (x->done == 0) {
+ ret = msleep_nsec(x, &x->wait.lock, 0, "wfci", INFSLP);
+ if (ret) {
+ mtx_leave(&x->wait.lock);
+ return (ret == EWOULDBLOCK) ? 0 : -ret;
+ }
+ }
+ x->done--;
+ mtx_leave(&x->wait.lock);
+
+ return 0;
+}
+
+static inline u_long
wait_for_completion_interruptible(struct completion *x)
{
int ret;
@@ -99,6 +126,16 @@ wait_for_completion_interruptible_timeout(struct completion *x, u_long timo)
}
static inline void
+complete(struct completion *x)
+{
+ mtx_enter(&x->wait.lock);
+ if (x->done != UINT_MAX)
+ x->done++;
+ mtx_leave(&x->wait.lock);
+ wakeup(x);
+}
+
+static inline void
complete_all(struct completion *x)
{
mtx_enter(&x->wait.lock);
diff --git a/sys/dev/pci/drm/include/linux/component.h b/sys/dev/pci/drm/include/linux/component.h
index e69de29bb2d..c20c085a61d 100644
--- a/sys/dev/pci/drm/include/linux/component.h
+++ b/sys/dev/pci/drm/include/linux/component.h
@@ -0,0 +1,8 @@
+/* Public domain. */
+
+#ifndef _LINUX_COMPONENT_H
+#define _LINUX_COMPONENT_H
+
+#define component_del(a, b)
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/debugfs.h b/sys/dev/pci/drm/include/linux/debugfs.h
index e69de29bb2d..bd5fc702ee0 100644
--- a/sys/dev/pci/drm/include/linux/debugfs.h
+++ b/sys/dev/pci/drm/include/linux/debugfs.h
@@ -0,0 +1,9 @@
+/* Public domain. */
+
+#ifndef _LINUX_DEBUGFS_H
+#define _LINUX_DEBUGFS_H
+
+struct debugfs_regset32 {
+};
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/debugobjects.h b/sys/dev/pci/drm/include/linux/debugobjects.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/debugobjects.h
diff --git a/sys/dev/pci/drm/include/linux/delay.h b/sys/dev/pci/drm/include/linux/delay.h
index 157ef90c3f3..19f0ef92204 100644
--- a/sys/dev/pci/drm/include/linux/delay.h
+++ b/sys/dev/pci/drm/include/linux/delay.h
@@ -31,4 +31,6 @@ mdelay(unsigned long msecs)
DELAY(1000);
}
+#define drm_msleep(x) mdelay(x)
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/device.h b/sys/dev/pci/drm/include/linux/device.h
index 21bcf29e1ad..14bf41401dc 100644
--- a/sys/dev/pci/drm/include/linux/device.h
+++ b/sys/dev/pci/drm/include/linux/device.h
@@ -12,6 +12,8 @@
#include <linux/ioport.h>
#include <linux/lockdep.h>
#include <linux/pm.h>
+#include <linux/kobject.h>
+#include <linux/ratelimit.h> /* dev_printk.h -> ratelimit.h */
struct device_node;
@@ -20,6 +22,8 @@ struct device_driver {
};
struct device_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct device *, struct device_attribute *, char *);
};
#define DEVICE_ATTR(_name, _mode, _show, _store) \
@@ -30,7 +34,6 @@ struct device_attribute {
#define dev_get_drvdata(x) NULL
#define dev_set_drvdata(x, y)
-#define dev_name(dev) ""
#define dev_pm_set_driver_flags(x, y)
@@ -52,6 +55,17 @@ struct device_attribute {
printf("drm:pid%d:%s *PRINTK* " fmt, curproc->p_p->ps_pid, \
__func__ , ## arg)
+#define dev_warn_ratelimited(dev, fmt, arg...) \
+ printf("drm:pid%d:%s *WARNING* " fmt, curproc->p_p->ps_pid, \
+ __func__ , ## arg)
+#define dev_notice_ratelimited(dev, fmt, arg...) \
+ printf("drm:pid%d:%s *NOTICE* " fmt, curproc->p_p->ps_pid, \
+ __func__ , ## arg)
+
+#define dev_err_once(dev, fmt, arg...) \
+ printf("drm:pid%d:%s *ERROR* " fmt, curproc->p_p->ps_pid, \
+ __func__ , ## arg)
+
#ifdef DRMDEBUG
#define dev_info(dev, fmt, arg...) \
printf("drm: " fmt, ## arg)
@@ -65,4 +79,13 @@ struct device_attribute {
do { } while(0)
#endif
+static inline const char *
+dev_driver_string(struct device *dev)
+{
+ return dev->dv_cfdata->cf_driver->cd_name;
+}
+
+/* should be bus id as string, ie 0000:00:02.0 */
+#define dev_name(dev) ""
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/dma-buf.h b/sys/dev/pci/drm/include/linux/dma-buf.h
index 69ee26eea33..04fa939f63a 100644
--- a/sys/dev/pci/drm/include/linux/dma-buf.h
+++ b/sys/dev/pci/drm/include/linux/dma-buf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dma-buf.h,v 1.1 2019/04/14 10:14:53 jsg Exp $ */
+/* $OpenBSD: dma-buf.h,v 1.2 2020/06/08 04:48:14 jsg Exp $ */
/*
* Copyright (c) 2018 Mark Kettenis
*
@@ -20,7 +20,8 @@
#include <sys/types.h>
#include <sys/systm.h>
-#include <linux/reservation.h>
+#include <linux/dma-resv.h>
+#include <linux/list.h>
struct dma_buf_ops;
@@ -29,9 +30,17 @@ struct dma_buf {
void *priv;
size_t size;
struct file *file;
+ struct list_head attachments;
+ struct dma_resv *resv;
};
-struct dma_buf_attachment;
+struct dma_buf_attachment {
+ void *importer_priv;
+};
+
+struct dma_buf_attach_ops {
+ void (*move_notify)(struct dma_buf_attachment *);
+};
void get_dma_buf(struct dma_buf *);
struct dma_buf *dma_buf_get(int);
@@ -47,7 +56,7 @@ struct dma_buf_export_info {
size_t size;
int flags;
void *priv;
- struct reservation_object *resv;
+ struct dma_resv *resv;
};
#define DEFINE_DMA_BUF_EXPORT_INFO(x) struct dma_buf_export_info x
diff --git a/sys/dev/pci/drm/include/linux/dma-fence-chain.h b/sys/dev/pci/drm/include/linux/dma-fence-chain.h
new file mode 100644
index 00000000000..8d1ac5d5337
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/dma-fence-chain.h
@@ -0,0 +1,9 @@
+/* Public domain. */
+
+#ifndef _LINUX_DMA_FENCE_CHAIN_H
+#define _LINUX_DMA_FENCE_CHAIN_H
+
+struct dma_fence_chain {
+};
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/dma-fence.h b/sys/dev/pci/drm/include/linux/dma-fence.h
index 5b94d067bb6..5b02546f7f4 100644
--- a/sys/dev/pci/drm/include/linux/dma-fence.h
+++ b/sys/dev/pci/drm/include/linux/dma-fence.h
@@ -18,16 +18,18 @@ struct dma_fence {
struct kref refcount;
const struct dma_fence_ops *ops;
unsigned long flags;
- unsigned int context;
- unsigned int seqno;
+ uint64_t context;
+ uint64_t seqno;
struct mutex *lock;
struct list_head cb_list;
int error;
struct rcu_head rcu;
+ ktime_t timestamp;
};
enum dma_fence_flag_bits {
DMA_FENCE_FLAG_SIGNALED_BIT,
+ DMA_FENCE_FLAG_TIMESTAMP_BIT,
DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
DMA_FENCE_FLAG_USER_BITS,
};
@@ -49,7 +51,7 @@ struct dma_fence_cb {
dma_fence_func_t func;
};
-unsigned int dma_fence_context_alloc(unsigned int);
+uint64_t dma_fence_context_alloc(unsigned int);
static inline struct dma_fence *
dma_fence_get(struct dma_fence *fence)
@@ -103,45 +105,43 @@ dma_fence_put(struct dma_fence *fence)
}
static inline int
-dma_fence_signal(struct dma_fence *fence)
+dma_fence_signal_locked(struct dma_fence *fence)
{
+ struct dma_fence_cb *cur, *tmp;
+ struct list_head cb_list;
+
if (fence == NULL)
return -EINVAL;
if (test_and_set_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
return -EINVAL;
- if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags)) {
- struct dma_fence_cb *cur, *tmp;
+ list_replace(&fence->cb_list, &cb_list);
- mtx_enter(fence->lock);
- list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) {
- list_del_init(&cur->node);
- cur->func(fence, cur);
- }
- mtx_leave(fence->lock);
+ fence->timestamp = ktime_get();
+ set_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags);
+
+ list_for_each_entry_safe(cur, tmp, &cb_list, node) {
+ INIT_LIST_HEAD(&cur->node);
+ cur->func(fence, cur);
}
return 0;
}
static inline int
-dma_fence_signal_locked(struct dma_fence *fence)
+dma_fence_signal(struct dma_fence *fence)
{
- struct dma_fence_cb *cur, *tmp;
+ int r;
if (fence == NULL)
return -EINVAL;
- if (test_and_set_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
- return -EINVAL;
-
- list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) {
- list_del_init(&cur->node);
- cur->func(fence, cur);
- }
+ mtx_enter(fence->lock);
+ r = dma_fence_signal_locked(fence);
+ mtx_leave(fence->lock);
- return 0;
+ return r;
}
static inline bool
@@ -213,7 +213,7 @@ dma_fence_enable_sw_signaling(struct dma_fence *fence)
static inline void
dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops,
- struct mutex *lock, unsigned context, unsigned seqno)
+ struct mutex *lock, uint64_t context, uint64_t seqno)
{
fence->ops = ops;
fence->lock = lock;
@@ -294,4 +294,6 @@ dma_fence_set_error(struct dma_fence *fence, int error)
long dma_fence_wait_any_timeout(struct dma_fence **, uint32_t, bool, long,
uint32_t *);
+struct dma_fence *dma_fence_get_stub(void);
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/dma-mapping.h b/sys/dev/pci/drm/include/linux/dma-mapping.h
index 5c33c31c5ea..1e06dac6d3e 100644
--- a/sys/dev/pci/drm/include/linux/dma-mapping.h
+++ b/sys/dev/pci/drm/include/linux/dma-mapping.h
@@ -4,10 +4,13 @@
#define _LINUX_DMA_MAPPING_H
#include <linux/sizes.h>
+#include <linux/scatterlist.h>
#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : (1ULL<<(n)) -1)
#define dma_set_coherent_mask(x, y) 0
#define dma_set_max_seg_size(x, y) 0
+#define dma_set_mask_and_coherent(x, y) 0
+#define dma_addressing_limited(x) false
#endif
diff --git a/sys/dev/pci/drm/include/linux/reservation.h b/sys/dev/pci/drm/include/linux/dma-resv.h
index 02166e815af..ee50d10f052 100644
--- a/sys/dev/pci/drm/include/linux/reservation.h
+++ b/sys/dev/pci/drm/include/linux/dma-resv.h
@@ -50,102 +50,52 @@ extern struct lock_class_key reservation_seqcount_class;
extern const char reservation_seqcount_string[];
/**
- * struct reservation_object_list - a list of shared fences
+ * struct dma_resv_list - a list of shared fences
* @rcu: for internal use
* @shared_count: table of shared fences
* @shared_max: for growing shared fence table
* @shared: shared fence table
*/
-struct reservation_object_list {
+struct dma_resv_list {
struct rcu_head rcu;
u32 shared_count, shared_max;
struct dma_fence __rcu *shared[];
};
/**
- * struct reservation_object - a reservation object manages fences for a buffer
+ * struct dma_resv - a reservation object manages fences for a buffer
* @lock: update side lock
* @seq: sequence count for managing RCU read-side synchronization
* @fence_excl: the exclusive fence, if there is one currently
* @fence: list of current shared fences
- * @staged: staged copy of shared fences for RCU updates
*/
-struct reservation_object {
+struct dma_resv {
struct ww_mutex lock;
seqcount_t seq;
struct dma_fence __rcu *fence_excl;
- struct reservation_object_list __rcu *fence;
- struct reservation_object_list *staged;
+ struct dma_resv_list __rcu *fence;
};
-#define reservation_object_held(obj) lockdep_is_held(&(obj)->lock.base)
-#define reservation_object_assert_held(obj) \
- lockdep_assert_held(&(obj)->lock.base)
+#define dma_resv_held(obj) lockdep_is_held(&(obj)->lock.base)
+#define dma_resv_assert_held(obj) lockdep_assert_held(&(obj)->lock.base)
/**
- * reservation_object_init - initialize a reservation object
- * @obj: the reservation object
- */
-static inline void
-reservation_object_init(struct reservation_object *obj)
-{
- ww_mutex_init(&obj->lock, &reservation_ww_class);
-
- __seqcount_init(&obj->seq, reservation_seqcount_string, &reservation_seqcount_class);
- RCU_INIT_POINTER(obj->fence, NULL);
- RCU_INIT_POINTER(obj->fence_excl, NULL);
- obj->staged = NULL;
-}
-
-/**
- * reservation_object_fini - destroys a reservation object
- * @obj: the reservation object
- */
-static inline void
-reservation_object_fini(struct reservation_object *obj)
-{
- int i;
- struct reservation_object_list *fobj;
- struct dma_fence *excl;
-
- /*
- * This object should be dead and all references must have
- * been released to it, so no need to be protected with rcu.
- */
- excl = rcu_dereference_protected(obj->fence_excl, 1);
- if (excl)
- dma_fence_put(excl);
-
- fobj = rcu_dereference_protected(obj->fence, 1);
- if (fobj) {
- for (i = 0; i < fobj->shared_count; ++i)
- dma_fence_put(rcu_dereference_protected(fobj->shared[i], 1));
-
- kfree(fobj);
- }
- kfree(obj->staged);
-
- ww_mutex_destroy(&obj->lock);
-}
-
-/**
- * reservation_object_get_list - get the reservation object's
+ * dma_resv_get_list - get the reservation object's
* shared fence list, with update-side lock held
* @obj: the reservation object
*
* Returns the shared fence list. Does NOT take references to
* the fence. The obj->lock must be held.
*/
-static inline struct reservation_object_list *
-reservation_object_get_list(struct reservation_object *obj)
+static inline struct dma_resv_list *dma_resv_get_list(struct dma_resv *obj)
{
return rcu_dereference_protected(obj->fence,
- reservation_object_held(obj));
+ dma_resv_held(obj));
}
/**
- * reservation_object_lock - lock the reservation object
+ * dma_resv_lock - lock the reservation object
* @obj: the reservation object
* @ctx: the locking context
*
@@ -159,15 +109,14 @@ reservation_object_get_list(struct reservation_object *obj)
* is detected. See ww_mutex_lock() and ww_acquire_init(). A reservation
* object may be locked by itself by passing NULL as @ctx.
*/
-static inline int
-reservation_object_lock(struct reservation_object *obj,
- struct ww_acquire_ctx *ctx)
+static inline int dma_resv_lock(struct dma_resv *obj,
+ struct ww_acquire_ctx *ctx)
{
return ww_mutex_lock(&obj->lock, ctx);
}
/**
- * reservation_object_lock_interruptible - lock the reservation object
+ * dma_resv_lock_interruptible - lock the reservation object
* @obj: the reservation object
* @ctx: the locking context
*
@@ -181,16 +130,45 @@ reservation_object_lock(struct reservation_object *obj,
* is detected. See ww_mutex_lock() and ww_acquire_init(). A reservation
* object may be locked by itself by passing NULL as @ctx.
*/
-static inline int
-reservation_object_lock_interruptible(struct reservation_object *obj,
- struct ww_acquire_ctx *ctx)
+static inline int dma_resv_lock_interruptible(struct dma_resv *obj,
+ struct ww_acquire_ctx *ctx)
{
return ww_mutex_lock_interruptible(&obj->lock, ctx);
}
+/**
+ * dma_resv_lock_slow - slowpath lock the reservation object
+ * @obj: the reservation object
+ * @ctx: the locking context
+ *
+ * Acquires the reservation object after a die case. This function
+ * will sleep until the lock becomes available. See dma_resv_lock() as
+ * well.
+ */
+static inline void dma_resv_lock_slow(struct dma_resv *obj,
+ struct ww_acquire_ctx *ctx)
+{
+ ww_mutex_lock_slow(&obj->lock, ctx);
+}
/**
- * reservation_object_trylock - trylock the reservation object
+ * dma_resv_lock_slow_interruptible - slowpath lock the reservation
+ * object, interruptible
+ * @obj: the reservation object
+ * @ctx: the locking context
+ *
+ * Acquires the reservation object interruptible after a die case. This function
+ * will sleep until the lock becomes available. See
+ * dma_resv_lock_interruptible() as well.
+ */
+static inline int dma_resv_lock_slow_interruptible(struct dma_resv *obj,
+ struct ww_acquire_ctx *ctx)
+{
+ return ww_mutex_lock_slow_interruptible(&obj->lock, ctx);
+}
+
+/**
+ * dma_resv_trylock - trylock the reservation object
* @obj: the reservation object
*
* Tries to lock the reservation object for exclusive access and modification.
@@ -203,44 +181,74 @@ reservation_object_lock_interruptible(struct reservation_object *obj,
*
* Returns true if the lock was acquired, false otherwise.
*/
-static inline bool __must_check
-reservation_object_trylock(struct reservation_object *obj)
+static inline bool __must_check dma_resv_trylock(struct dma_resv *obj)
{
return ww_mutex_trylock(&obj->lock);
}
/**
- * reservation_object_unlock - unlock the reservation object
+ * dma_resv_is_locked - is the reservation object locked
+ * @obj: the reservation object
+ *
+ * Returns true if the mutex is locked, false if unlocked.
+ */
+static inline bool dma_resv_is_locked(struct dma_resv *obj)
+{
+ return ww_mutex_is_locked(&obj->lock);
+}
+
+/**
+ * dma_resv_locking_ctx - returns the context used to lock the object
+ * @obj: the reservation object
+ *
+ * Returns the context used to lock a reservation object or NULL if no context
+ * was used or the object is not locked at all.
+ */
+static inline struct ww_acquire_ctx *dma_resv_locking_ctx(struct dma_resv *obj)
+{
+ return READ_ONCE(obj->lock.ctx);
+}
+
+/**
+ * dma_resv_unlock - unlock the reservation object
* @obj: the reservation object
*
* Unlocks the reservation object following exclusive access.
*/
-static inline void
-reservation_object_unlock(struct reservation_object *obj)
+static inline void dma_resv_unlock(struct dma_resv *obj)
{
+#ifdef CONFIG_DEBUG_MUTEXES
+ /* Test shared fence slot reservation */
+ if (rcu_access_pointer(obj->fence)) {
+ struct dma_resv_list *fence = dma_resv_get_list(obj);
+
+ fence->shared_max = fence->shared_count;
+ }
+#endif
ww_mutex_unlock(&obj->lock);
}
/**
- * reservation_object_get_excl - get the reservation object's
+ * dma_resv_get_excl - get the reservation object's
* exclusive fence, with update-side lock held
* @obj: the reservation object
*
* Returns the exclusive fence (if any). Does NOT take a
- * reference. The obj->lock must be held.
+ * reference. Writers must hold obj->lock, readers may only
+ * hold a RCU read side lock.
*
* RETURNS
* The exclusive fence or NULL
*/
static inline struct dma_fence *
-reservation_object_get_excl(struct reservation_object *obj)
+dma_resv_get_excl(struct dma_resv *obj)
{
return rcu_dereference_protected(obj->fence_excl,
- reservation_object_held(obj));
+ dma_resv_held(obj));
}
/**
- * reservation_object_get_excl_rcu - get the reservation object's
+ * dma_resv_get_excl_rcu - get the reservation object's
* exclusive fence, without lock held.
* @obj: the reservation object
*
@@ -251,7 +259,7 @@ reservation_object_get_excl(struct reservation_object *obj)
* The exclusive fence or NULL if none
*/
static inline struct dma_fence *
-reservation_object_get_excl_rcu(struct reservation_object *obj)
+dma_resv_get_excl_rcu(struct dma_resv *obj)
{
struct dma_fence *fence;
@@ -265,26 +273,23 @@ reservation_object_get_excl_rcu(struct reservation_object *obj)
return fence;
}
-int reservation_object_reserve_shared(struct reservation_object *obj);
-void reservation_object_add_shared_fence(struct reservation_object *obj,
- struct dma_fence *fence);
+void dma_resv_init(struct dma_resv *obj);
+void dma_resv_fini(struct dma_resv *obj);
+int dma_resv_reserve_shared(struct dma_resv *obj, unsigned int num_fences);
+void dma_resv_add_shared_fence(struct dma_resv *obj, struct dma_fence *fence);
-void reservation_object_add_excl_fence(struct reservation_object *obj,
- struct dma_fence *fence);
+void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence);
-int reservation_object_get_fences_rcu(struct reservation_object *obj,
- struct dma_fence **pfence_excl,
- unsigned *pshared_count,
- struct dma_fence ***pshared);
+int dma_resv_get_fences_rcu(struct dma_resv *obj,
+ struct dma_fence **pfence_excl,
+ unsigned *pshared_count,
+ struct dma_fence ***pshared);
-int reservation_object_copy_fences(struct reservation_object *dst,
- struct reservation_object *src);
+int dma_resv_copy_fences(struct dma_resv *dst, struct dma_resv *src);
-long reservation_object_wait_timeout_rcu(struct reservation_object *obj,
- bool wait_all, bool intr,
- unsigned long timeout);
+long dma_resv_wait_timeout_rcu(struct dma_resv *obj, bool wait_all, bool intr,
+ unsigned long timeout);
-bool reservation_object_test_signaled_rcu(struct reservation_object *obj,
- bool test_all);
+bool dma_resv_test_signaled_rcu(struct dma_resv *obj, bool test_all);
#endif /* _LINUX_RESERVATION_H */
diff --git a/sys/dev/pci/drm/include/linux/errno.h b/sys/dev/pci/drm/include/linux/errno.h
index 99c6d662fcf..2a85ac1e7cc 100644
--- a/sys/dev/pci/drm/include/linux/errno.h
+++ b/sys/dev/pci/drm/include/linux/errno.h
@@ -11,5 +11,6 @@
#define ENOTSUPP ENOTSUP
#define ENODATA ENOTSUP
#define ECHRNG EINVAL
+#define EHWPOISON EIO
#endif
diff --git a/sys/dev/pci/drm/include/linux/fb.h b/sys/dev/pci/drm/include/linux/fb.h
index 463de7f2cf7..70170be0b69 100644
--- a/sys/dev/pci/drm/include/linux/fb.h
+++ b/sys/dev/pci/drm/include/linux/fb.h
@@ -8,6 +8,14 @@
#include <linux/notifier.h>
#include <linux/backlight.h>
#include <linux/kgdb.h>
+#include <linux/fs.h>
+
+struct fb_cmap;
+struct fb_fillrect;
+struct fb_copyarea;
+struct fb_image;
+
+struct apertures_struct;
struct fb_var_screeninfo {
int pixclock;
@@ -21,8 +29,11 @@ struct fb_info {
void *par;
int fbcon_rotate_hint;
bool skip_vt_switch;
+ int flags;
};
+#define KHZ2PICOS(a) (1000000000UL/(a))
+
#define FB_BLANK_UNBLANK 0
#define FB_BLANK_NORMAL 1
#define FB_BLANK_HSYNC_SUSPEND 2
@@ -32,14 +43,45 @@ struct fb_info {
#define FBINFO_STATE_RUNNING 0
#define FBINFO_STATE_SUSPENDED 1
+#define FBINFO_HIDE_SMEM_START 0
+
#define FB_ROTATE_UR 0
#define FB_ROTATE_CW 1
#define FB_ROTATE_UD 2
#define FB_ROTATE_CCW 3
-#define framebuffer_alloc(flags, device) \
- kzalloc(sizeof(struct fb_info), GFP_KERNEL)
+static inline struct fb_info *
+framebuffer_alloc(size_t size, void *dev)
+{
+ return kzalloc(sizeof(struct fb_info) + size, GFP_KERNEL);
+}
+
+static inline void
+fb_set_suspend(struct fb_info *fbi, int s)
+{
+}
+
+static inline void
+framebuffer_release(struct fb_info *fbi)
+{
+ kfree(fbi);
+}
+
+static inline int
+fb_get_options(const char *name, char **opt)
+{
+ return 0;
+}
+
+static inline int
+register_framebuffer(struct fb_info *fbi)
+{
+ return 0;
+}
-#define fb_set_suspend(x, y)
+static inline void
+unregister_framebuffer(struct fb_info *fbi)
+{
+}
#endif
diff --git a/sys/dev/pci/drm/include/linux/firmware.h b/sys/dev/pci/drm/include/linux/firmware.h
index 4e24fc963ca..e3406bf6787 100644
--- a/sys/dev/pci/drm/include/linux/firmware.h
+++ b/sys/dev/pci/drm/include/linux/firmware.h
@@ -7,6 +7,7 @@
#include <sys/malloc.h>
#include <sys/device.h>
#include <linux/types.h>
+#include <linux/gfp.h>
#ifndef __DECONST
#define __DECONST(type, var) ((type)(__uintptr_t)(const void *)(var))
diff --git a/sys/dev/pci/drm/include/linux/fs.h b/sys/dev/pci/drm/include/linux/fs.h
index 19ca23adc33..be033dc5d11 100644
--- a/sys/dev/pci/drm/include/linux/fs.h
+++ b/sys/dev/pci/drm/include/linux/fs.h
@@ -12,6 +12,8 @@
#include <linux/pid.h>
#include <linux/radix-tree.h>
#include <linux/wait_bit.h>
+#include <linux/err.h>
+#include <linux/sched/signal.h> /* via percpu-rwsem.h -> rcuwait.h */
struct address_space;
diff --git a/sys/dev/pci/drm/include/linux/ftrace.h b/sys/dev/pci/drm/include/linux/ftrace.h
new file mode 100644
index 00000000000..2754e2477b9
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/ftrace.h
@@ -0,0 +1,8 @@
+/* Public domain. */
+
+#ifndef _LINUX_FTRACE_H
+#define _LINUX_FTRACE_H
+
+#include <linux/kallsyms.h>
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/gfp.h b/sys/dev/pci/drm/include/linux/gfp.h
index dcffa2ef49d..d1c8d60162d 100644
--- a/sys/dev/pci/drm/include/linux/gfp.h
+++ b/sys/dev/pci/drm/include/linux/gfp.h
@@ -7,6 +7,8 @@
#include <sys/malloc.h>
#include <uvm/uvm_extern.h>
+#include <linux/mmzone.h>
+
#define __GFP_ZERO M_ZERO
#define __GFP_DMA32 0x00010000
#define __GFP_NOWARN 0
diff --git a/sys/dev/pci/drm/include/linux/hashtable.h b/sys/dev/pci/drm/include/linux/hashtable.h
index 26660bf65bf..ccc72458351 100644
--- a/sys/dev/pci/drm/include/linux/hashtable.h
+++ b/sys/dev/pci/drm/include/linux/hashtable.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: hashtable.h,v 1.1 2019/04/14 10:14:53 jsg Exp $ */
+/* $OpenBSD: hashtable.h,v 1.2 2020/06/08 04:48:14 jsg Exp $ */
/*
* Copyright (c) 2017 Mark Kettenis
*
@@ -19,6 +19,7 @@
#define _LINUX_HASHTABLE_H
#include <linux/list.h>
+#include <linux/hash.h>
#define DECLARE_HASHTABLE(name, bits) struct hlist_head name[1 << (bits)]
diff --git a/sys/dev/pci/drm/include/linux/hdmi.h b/sys/dev/pci/drm/include/linux/hdmi.h
index 4f3febc0f97..9613d796cfb 100644
--- a/sys/dev/pci/drm/include/linux/hdmi.h
+++ b/sys/dev/pci/drm/include/linux/hdmi.h
@@ -27,11 +27,27 @@
#include <linux/types.h>
#include <linux/device.h>
+enum hdmi_packet_type {
+ HDMI_PACKET_TYPE_NULL = 0x00,
+ HDMI_PACKET_TYPE_AUDIO_CLOCK_REGEN = 0x01,
+ HDMI_PACKET_TYPE_AUDIO_SAMPLE = 0x02,
+ HDMI_PACKET_TYPE_GENERAL_CONTROL = 0x03,
+ HDMI_PACKET_TYPE_ACP = 0x04,
+ HDMI_PACKET_TYPE_ISRC1 = 0x05,
+ HDMI_PACKET_TYPE_ISRC2 = 0x06,
+ HDMI_PACKET_TYPE_ONE_BIT_AUDIO_SAMPLE = 0x07,
+ HDMI_PACKET_TYPE_DST_AUDIO = 0x08,
+ HDMI_PACKET_TYPE_HBR_AUDIO_STREAM = 0x09,
+ HDMI_PACKET_TYPE_GAMUT_METADATA = 0x0a,
+ /* + enum hdmi_infoframe_type */
+};
+
enum hdmi_infoframe_type {
HDMI_INFOFRAME_TYPE_VENDOR = 0x81,
HDMI_INFOFRAME_TYPE_AVI = 0x82,
HDMI_INFOFRAME_TYPE_SPD = 0x83,
HDMI_INFOFRAME_TYPE_AUDIO = 0x84,
+ HDMI_INFOFRAME_TYPE_DRM = 0x87,
};
#define HDMI_IEEE_OUI 0x000c03
@@ -40,6 +56,7 @@ enum hdmi_infoframe_type {
#define HDMI_AVI_INFOFRAME_SIZE 13
#define HDMI_SPD_INFOFRAME_SIZE 25
#define HDMI_AUDIO_INFOFRAME_SIZE 10
+#define HDMI_DRM_INFOFRAME_SIZE 26
#define HDMI_INFOFRAME_SIZE(type) \
(HDMI_INFOFRAME_HEADER_SIZE + HDMI_ ## type ## _INFOFRAME_SIZE)
@@ -137,6 +154,17 @@ enum hdmi_content_type {
HDMI_CONTENT_TYPE_GAME,
};
+enum hdmi_metadata_type {
+ HDMI_STATIC_METADATA_TYPE1 = 1,
+};
+
+enum hdmi_eotf {
+ HDMI_EOTF_TRADITIONAL_GAMMA_SDR,
+ HDMI_EOTF_TRADITIONAL_GAMMA_HDR,
+ HDMI_EOTF_SMPTE_ST2084,
+ HDMI_EOTF_BT_2100_HLG,
+};
+
struct hdmi_avi_infoframe {
enum hdmi_infoframe_type type;
unsigned char version;
@@ -160,9 +188,37 @@ struct hdmi_avi_infoframe {
unsigned short right_bar;
};
-int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame);
+/* DRM Infoframe as per CTA 861.G spec */
+struct hdmi_drm_infoframe {
+ enum hdmi_infoframe_type type;
+ unsigned char version;
+ unsigned char length;
+ enum hdmi_eotf eotf;
+ enum hdmi_metadata_type metadata_type;
+ struct {
+ u16 x, y;
+ } display_primaries[3];
+ struct {
+ u16 x, y;
+ } white_point;
+ u16 max_display_mastering_luminance;
+ u16 min_display_mastering_luminance;
+ u16 max_cll;
+ u16 max_fall;
+};
+
+void hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame);
ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,
size_t size);
+ssize_t hdmi_avi_infoframe_pack_only(const struct hdmi_avi_infoframe *frame,
+ void *buffer, size_t size);
+int hdmi_avi_infoframe_check(struct hdmi_avi_infoframe *frame);
+int hdmi_drm_infoframe_init(struct hdmi_drm_infoframe *frame);
+ssize_t hdmi_drm_infoframe_pack(struct hdmi_drm_infoframe *frame, void *buffer,
+ size_t size);
+ssize_t hdmi_drm_infoframe_pack_only(const struct hdmi_drm_infoframe *frame,
+ void *buffer, size_t size);
+int hdmi_drm_infoframe_check(struct hdmi_drm_infoframe *frame);
enum hdmi_spd_sdi {
HDMI_SPD_SDI_UNKNOWN,
@@ -194,6 +250,9 @@ int hdmi_spd_infoframe_init(struct hdmi_spd_infoframe *frame,
const char *vendor, const char *product);
ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame, void *buffer,
size_t size);
+ssize_t hdmi_spd_infoframe_pack_only(const struct hdmi_spd_infoframe *frame,
+ void *buffer, size_t size);
+int hdmi_spd_infoframe_check(struct hdmi_spd_infoframe *frame);
enum hdmi_audio_coding_type {
HDMI_AUDIO_CODING_TYPE_STREAM,
@@ -272,6 +331,9 @@ struct hdmi_audio_infoframe {
int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame);
ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
void *buffer, size_t size);
+ssize_t hdmi_audio_infoframe_pack_only(const struct hdmi_audio_infoframe *frame,
+ void *buffer, size_t size);
+int hdmi_audio_infoframe_check(struct hdmi_audio_infoframe *frame);
enum hdmi_3d_structure {
HDMI_3D_STRUCTURE_INVALID = -1,
@@ -296,9 +358,39 @@ struct hdmi_vendor_infoframe {
unsigned int s3d_ext_data;
};
+/* HDR Metadata as per 861.G spec */
+struct hdr_static_metadata {
+ __u8 eotf;
+ __u8 metadata_type;
+ __u16 max_cll;
+ __u16 max_fall;
+ __u16 min_cll;
+};
+
+/**
+ * struct hdr_sink_metadata - HDR sink metadata
+ *
+ * Metadata Information read from Sink's EDID
+ */
+struct hdr_sink_metadata {
+ /**
+ * @metadata_type: Static_Metadata_Descriptor_ID.
+ */
+ __u32 metadata_type;
+ /**
+ * @hdmi_type1: HDR Metadata Infoframe.
+ */
+ union {
+ struct hdr_static_metadata hdmi_type1;
+ };
+};
+
int hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe *frame);
ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
void *buffer, size_t size);
+ssize_t hdmi_vendor_infoframe_pack_only(const struct hdmi_vendor_infoframe *frame,
+ void *buffer, size_t size);
+int hdmi_vendor_infoframe_check(struct hdmi_vendor_infoframe *frame);
union hdmi_vendor_any_infoframe {
struct {
@@ -317,6 +409,7 @@ union hdmi_vendor_any_infoframe {
* @spd: spd infoframe
* @vendor: union of all vendor infoframes
* @audio: audio infoframe
+ * @drm: Dynamic Range and Mastering infoframe
*
* This is used by the generic pack function. This works since all infoframes
* have the same header which also indicates which type of infoframe should be
@@ -328,12 +421,17 @@ union hdmi_infoframe {
struct hdmi_spd_infoframe spd;
union hdmi_vendor_any_infoframe vendor;
struct hdmi_audio_infoframe audio;
+ struct hdmi_drm_infoframe drm;
};
-ssize_t
-hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buffer, size_t size);
-int hdmi_infoframe_unpack(union hdmi_infoframe *frame, void *buffer);
+ssize_t hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buffer,
+ size_t size);
+ssize_t hdmi_infoframe_pack_only(const union hdmi_infoframe *frame,
+ void *buffer, size_t size);
+int hdmi_infoframe_check(union hdmi_infoframe *frame);
+int hdmi_infoframe_unpack(union hdmi_infoframe *frame,
+ const void *buffer, size_t size);
void hdmi_infoframe_log(const char *level, struct device *dev,
- union hdmi_infoframe *frame);
+ const union hdmi_infoframe *frame);
#endif /* _DRM_HDMI_H */
diff --git a/sys/dev/pci/drm/include/linux/highmem.h b/sys/dev/pci/drm/include/linux/highmem.h
index 39385671748..36405597f9e 100644
--- a/sys/dev/pci/drm/include/linux/highmem.h
+++ b/sys/dev/pci/drm/include/linux/highmem.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: highmem.h,v 1.1 2019/04/14 10:14:53 jsg Exp $ */
+/* $OpenBSD: highmem.h,v 1.2 2020/06/08 04:48:14 jsg Exp $ */
/*
* Copyright (c) 2013, 2014, 2015 Mark Kettenis
*
@@ -18,6 +18,7 @@
#ifndef _LINUX_HIGHMEM_H
#define _LINUX_HIGHMEM_H
+#include <sys/param.h>
#include <uvm/uvm_extern.h>
#include <linux/uaccess.h>
diff --git a/sys/dev/pci/drm/include/linux/hmm.h b/sys/dev/pci/drm/include/linux/hmm.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/hmm.h
diff --git a/sys/dev/pci/drm/include/linux/i2c.h b/sys/dev/pci/drm/include/linux/i2c.h
index 3a91dc8dcd3..0d0ff3f44be 100644
--- a/sys/dev/pci/drm/include/linux/i2c.h
+++ b/sys/dev/pci/drm/include/linux/i2c.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: i2c.h,v 1.1 2019/04/14 10:14:53 jsg Exp $ */
+/* $OpenBSD: i2c.h,v 1.2 2020/06/08 04:48:14 jsg Exp $ */
/*
* Copyright (c) 2017 Mark Kettenis
*
@@ -33,6 +33,8 @@ struct i2c_algorithm;
#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0
#define I2C_FUNC_10BIT_ADDR 0
+struct i2c_lock_operations;
+
struct i2c_adapter {
struct i2c_controller ic;
@@ -40,10 +42,17 @@ struct i2c_adapter {
const struct i2c_algorithm *algo;
void *algo_data;
int retries;
+ const struct i2c_lock_operations *lock_ops;
void *data;
};
+struct i2c_lock_operations {
+ void (*lock_bus)(struct i2c_adapter *, unsigned int);
+ int (*trylock_bus)(struct i2c_adapter *, unsigned int);
+ void (*unlock_bus)(struct i2c_adapter *, unsigned int);
+};
+
#define I2C_NAME_SIZE 20
struct i2c_msg {
diff --git a/sys/dev/pci/drm/include/linux/idr.h b/sys/dev/pci/drm/include/linux/idr.h
index 501a89577fa..b327fa9e4a4 100644
--- a/sys/dev/pci/drm/include/linux/idr.h
+++ b/sys/dev/pci/drm/include/linux/idr.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: idr.h,v 1.2 2019/05/13 16:23:15 jsg Exp $ */
+/* $OpenBSD: idr.h,v 1.3 2020/06/08 04:48:14 jsg Exp $ */
/*
* Copyright (c) 2016 Mark Kettenis
*
@@ -18,8 +18,11 @@
#ifndef _LINUX_IDR_H
#define _LINUX_IDR_H
+#include <sys/types.h>
#include <sys/tree.h>
+#include <linux/radix-tree.h>
+
struct idr_entry {
SPLAY_ENTRY(idr_entry) entry;
int id;
diff --git a/sys/dev/pci/drm/include/linux/init.h b/sys/dev/pci/drm/include/linux/init.h
index e69de29bb2d..4f0355101f7 100644
--- a/sys/dev/pci/drm/include/linux/init.h
+++ b/sys/dev/pci/drm/include/linux/init.h
@@ -0,0 +1,8 @@
+/* Public domain. */
+
+#ifndef _LINUX_INIT_H
+#define _LINUX_INIT_H
+
+#define __initconst
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/intel-iommu.h b/sys/dev/pci/drm/include/linux/intel-iommu.h
index e69de29bb2d..9cab2c2a0e8 100644
--- a/sys/dev/pci/drm/include/linux/intel-iommu.h
+++ b/sys/dev/pci/drm/include/linux/intel-iommu.h
@@ -0,0 +1,8 @@
+/* Public domain. */
+
+#ifndef _INTEL_IOMMU_H_
+#define _INTEL_IOMMU_H_
+
+#include <linux/dma-mapping.h> /* via linux/iova.h */
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/interrupt.h b/sys/dev/pci/drm/include/linux/interrupt.h
index 8390fbdf3ca..459fe3341d4 100644
--- a/sys/dev/pci/drm/include/linux/interrupt.h
+++ b/sys/dev/pci/drm/include/linux/interrupt.h
@@ -10,6 +10,7 @@
#include <linux/irqflags.h>
#include <linux/atomic.h>
#include <linux/compiler.h>
+#include <linux/irqreturn.h>
#define IRQF_SHARED 0
@@ -19,6 +20,8 @@
#define request_irq(irq, hdlr, flags, name, dev) (0)
#define free_irq(irq, dev)
+typedef irqreturn_t (*irq_handler_t)(int, void *);
+
struct tasklet_struct {
void (*func)(unsigned long);
unsigned long data;
@@ -86,4 +89,18 @@ tasklet_hi_schedule(struct tasklet_struct *ts)
task_add(taskletq, &ts->task);
}
+static inline void
+tasklet_disable_nosync(struct tasklet_struct *ts)
+{
+ atomic_inc(&ts->count);
+ smp_mb__after_atomic();
+}
+
+static inline void
+tasklet_enable(struct tasklet_struct *ts)
+{
+ smp_mb__before_atomic();
+ atomic_dec(&ts->count);
+}
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/io-64-nonatomic-lo-hi.h b/sys/dev/pci/drm/include/linux/io-64-nonatomic-lo-hi.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/io-64-nonatomic-lo-hi.h
diff --git a/sys/dev/pci/drm/include/linux/io.h b/sys/dev/pci/drm/include/linux/io.h
index 2b9e956c3fc..b88352f733a 100644
--- a/sys/dev/pci/drm/include/linux/io.h
+++ b/sys/dev/pci/drm/include/linux/io.h
@@ -3,9 +3,13 @@
#ifndef _LINUX_IO_H
#define _LINUX_IO_H
+#include <sys/types.h>
#include <sys/systm.h>
+#include <sys/memrange.h> /* for MDF_WRITECOMBINE */
+
#include <linux/types.h>
#include <linux/compiler.h>
+#include <linux/vmalloc.h>
#define memcpy_toio(d, s, n) memcpy(d, s, n)
#define memcpy_fromio(d, s, n) memcpy(d, s, n)
@@ -68,4 +72,9 @@ iowrite64(u64 val, volatile void __iomem *addr)
#define readq(p) ioread64(p)
#define writeq(v, p) iowrite64(v, p)
+int drm_mtrr_add(unsigned long, size_t, int);
+int drm_mtrr_del(int, unsigned long, size_t, int);
+
+#define DRM_MTRR_WC MDF_WRITECOMBINE
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/ipc.h b/sys/dev/pci/drm/include/linux/ipc.h
new file mode 100644
index 00000000000..e738818c92e
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/ipc.h
@@ -0,0 +1,8 @@
+/* Public domain. */
+
+#ifndef _LINUX_IPC_H
+#define _LINUX_IPC_H
+
+#include <linux/workqueue.h> /* via linux/rhashtable-types.h */
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/kallsyms.h b/sys/dev/pci/drm/include/linux/kallsyms.h
new file mode 100644
index 00000000000..4dc9fabd0d1
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/kallsyms.h
@@ -0,0 +1,8 @@
+/* Public domain. */
+
+#ifndef _LINUX_KALLSYMS_H
+#define _LINUX_KALLSYMS_H
+
+#include <linux/module.h>
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/kconfig.h b/sys/dev/pci/drm/include/linux/kconfig.h
index 86aa9464a9c..586553e40e9 100644
--- a/sys/dev/pci/drm/include/linux/kconfig.h
+++ b/sys/dev/pci/drm/include/linux/kconfig.h
@@ -7,8 +7,16 @@
#include <generated/autoconf.h>
-#define IS_ENABLED(x) x - 0
-#define IS_BUILTIN(x) 1
+#define __NEWARG1 __newarg,
+#define __is_defined(x) __is_defined2(x)
+#define __is_defined2(x) __is_defined3(__NEWARG##x)
+#define __is_defined3(x) __is_defined4(x 1, 0)
+#define __is_defined4(a, b, ...) b
+
+#define IS_ENABLED(x) __is_defined(x)
+#define IS_REACHABLE(x) __is_defined(x)
+#define IS_BUILTIN(x) __is_defined(x)
+#define IS_MODULE(x) 0
#if BYTE_ORDER == BIG_ENDIAN
#define __BIG_ENDIAN
diff --git a/sys/dev/pci/drm/include/linux/kernel.h b/sys/dev/pci/drm/include/linux/kernel.h
index 99fa7b4bb8b..059680589db 100644
--- a/sys/dev/pci/drm/include/linux/kernel.h
+++ b/sys/dev/pci/drm/include/linux/kernel.h
@@ -36,8 +36,6 @@
#define U64_C(x) UINT64_C(x)
#define U64_MAX UINT64_MAX
-#define IS_ALIGNED(x, y) (((x) & ((y) - 1)) == 0)
-
#define ARRAY_SIZE nitems
#define lower_32_bits(n) ((u32)(n))
@@ -66,6 +64,7 @@
#define mult_frac(x, n, d) (((x) * (n)) / (d))
+#define roundup2(x, y) (((x) + ((y) - 1)) & (~((__typeof(x))(y) - 1)))
#define round_up(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
#define round_down(x, y) (((x) / (y)) * (y)) /* y is power of two */
#define rounddown(x, y) (((x) / (y)) * (y)) /* arbitary y */
@@ -76,6 +75,9 @@
#define DIV_ROUND_CLOSEST(x, y) (((x) + ((y) / 2)) / (y))
#define DIV_ROUND_CLOSEST_ULL(x, y) DIV_ROUND_CLOSEST(x, y)
+#define IS_ALIGNED(x, y) (((x) & ((y) - 1)) == 0)
+#define PTR_ALIGN(x, y) ((__typeof(x))roundup2((unsigned long)(x), (y)))
+
static inline char *
kasprintf(int flags, const char *fmt, ...)
{
@@ -114,6 +116,18 @@ kvasprintf(int flags, const char *fmt, va_list ap)
}
static inline int
+vscnprintf(char *buf, size_t size, const char *fmt, va_list ap)
+{
+ int nc;
+
+ nc = vsnprintf(buf, size, fmt, ap);
+ if (nc > (size - 1))
+ return (size - 1);
+ else
+ return nc;
+}
+
+static inline int
_in_dbg_master(void)
{
#ifdef DDB
@@ -129,8 +143,13 @@ _in_dbg_master(void)
#define add_taint(x, y)
#define TAINT_MACHINE_CHECK 0
+#define TAINT_WARN 1
#define LOCKDEP_STILL_OK 0
#define u64_to_user_ptr(x) ((void *)(uintptr_t)(x))
+#define _RET_IP_ __builtin_return_address(0)
+
+#define STUB() do { printf("%s: stub\n", __func__); } while(0)
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/kernfs.h b/sys/dev/pci/drm/include/linux/kernfs.h
new file mode 100644
index 00000000000..3d24789dfee
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/kernfs.h
@@ -0,0 +1,9 @@
+/* Public domain. */
+
+#ifndef _LINUX_KERNFS_H
+#define _LINUX_KERNFS_H
+
+#include <linux/err.h>
+#include <linux/idr.h>
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/kgdb.h b/sys/dev/pci/drm/include/linux/kgdb.h
index 874a0ebe0be..86dee85a2f0 100644
--- a/sys/dev/pci/drm/include/linux/kgdb.h
+++ b/sys/dev/pci/drm/include/linux/kgdb.h
@@ -3,6 +3,7 @@
#ifndef _LINUX_KGDB_H
#define _LINUX_KGDB_H
+#include <sys/types.h>
#include <sys/systm.h>
static inline int
diff --git a/sys/dev/pci/drm/include/linux/kmemleak.h b/sys/dev/pci/drm/include/linux/kmemleak.h
new file mode 100644
index 00000000000..30857919af2
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/kmemleak.h
@@ -0,0 +1,8 @@
+/* Public domain. */
+
+#ifndef _LINUX_KMEMLEAK_H
+#define _LINUX_KMEMLEAK_H
+
+#define kmemleak_update_trace(x)
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/kref.h b/sys/dev/pci/drm/include/linux/kref.h
index 1fbf37133cf..4d16577e749 100644
--- a/sys/dev/pci/drm/include/linux/kref.h
+++ b/sys/dev/pci/drm/include/linux/kref.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: kref.h,v 1.1 2019/04/14 10:14:53 jsg Exp $ */
+/* $OpenBSD: kref.h,v 1.2 2020/06/08 04:48:14 jsg Exp $ */
/*
* Copyright (c) 2015 Mark Kettenis
*
@@ -92,4 +92,21 @@ kref_put_mutex(struct kref *kref, void (*release)(struct kref *kref),
return 0;
}
+static inline int
+kref_put_lock(struct kref *kref, void (*release)(struct kref *kref),
+ struct mutex *lock)
+{
+ if (!atomic_add_unless(&kref->refcount, -1, 1)) {
+ mtx_enter(lock);
+ if (likely(atomic_dec_and_test(&kref->refcount))) {
+ release(kref);
+ return 1;
+ }
+ mtx_leave(lock);
+ return 0;
+ }
+
+ return 0;
+}
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/ktime.h b/sys/dev/pci/drm/include/linux/ktime.h
index c4e78551b10..7e5ccf322da 100644
--- a/sys/dev/pci/drm/include/linux/ktime.h
+++ b/sys/dev/pci/drm/include/linux/ktime.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ktime.h,v 1.1 2019/04/14 10:14:53 jsg Exp $ */
+/* $OpenBSD: ktime.h,v 1.2 2020/06/08 04:48:14 jsg Exp $ */
/*
* Copyright (c) 2013, 2014, 2015 Mark Kettenis
*
@@ -101,6 +101,12 @@ ktime_add(struct timeval a, struct timeval b)
}
static inline struct timeval
+ktime_add_us(struct timeval tv, int64_t us)
+{
+ return ns_to_timeval(timeval_to_ns(&tv) + (us * NSEC_PER_USEC));
+}
+
+static inline struct timeval
ktime_add_ns(struct timeval tv, int64_t ns)
{
return ns_to_timeval(timeval_to_ns(&tv) + ns);
diff --git a/sys/dev/pci/drm/include/linux/list.h b/sys/dev/pci/drm/include/linux/list.h
index cf05e6f7ad7..115580dbc0d 100644
--- a/sys/dev/pci/drm/include/linux/list.h
+++ b/sys/dev/pci/drm/include/linux/list.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: list.h,v 1.1 2019/04/14 10:14:53 jsg Exp $ */
+/* $OpenBSD: list.h,v 1.2 2020/06/08 04:48:14 jsg Exp $ */
/* drm_linux_list.h -- linux list functions for the BSDs.
* Created: Mon Apr 7 14:30:16 1999 by anholt@FreeBSD.org
*/
@@ -36,6 +36,7 @@
#include <sys/param.h>
#include <linux/kernel.h>
#include <linux/types.h>
+#include <linux/poison.h>
#define list_entry(ptr, type, member) container_of(ptr, type, member)
@@ -61,6 +62,13 @@ list_is_singular(const struct list_head *head) {
}
static inline int
+list_is_first(const struct list_head *list,
+ const struct list_head *head)
+{
+ return list->prev == head;
+}
+
+static inline int
list_is_last(const struct list_head *list,
const struct list_head *head)
{
@@ -121,6 +129,18 @@ static inline void list_move_tail(struct list_head *list,
}
static inline void
+list_bulk_move_tail(struct list_head *head, struct list_head *first,
+ struct list_head *last)
+{
+ first->prev->next = last->next;
+ last->next->prev = first->prev;
+ head->prev->next = first;
+ first->prev = head->prev;
+ last->next = head;
+ head->prev = last;
+}
+
+static inline void
list_del_init(struct list_head *entry) {
(entry)->next->prev = (entry)->prev;
(entry)->prev->next = (entry)->next;
@@ -133,6 +153,9 @@ list_del_init(struct list_head *entry) {
#define list_prev_entry(pos, member) \
list_entry(((pos)->member.prev), typeof(*(pos)), member)
+#define list_safe_reset_next(pos, n, member) \
+ n = list_next_entry(pos, member)
+
#define list_for_each(entry, head) \
for (entry = (head)->next; entry != head; entry = (entry)->next)
diff --git a/sys/dev/pci/drm/include/linux/llist.h b/sys/dev/pci/drm/include/linux/llist.h
index aea86b4faff..8c0b37da123 100644
--- a/sys/dev/pci/drm/include/linux/llist.h
+++ b/sys/dev/pci/drm/include/linux/llist.h
@@ -49,6 +49,19 @@ llist_add(struct llist_node *new, struct llist_head *head)
return (first == NULL);
}
+static inline bool
+llist_add_batch(struct llist_node *new_first, struct llist_node *new_last,
+ struct llist_head *head)
+{
+ struct llist_node *first;
+
+ do {
+ new_last->next = first = head->first;
+ } while (atomic_cas_ptr(&head->first, first, new_first) != first);
+
+ return (first == NULL);
+}
+
static inline void
init_llist_head(struct llist_head *head)
{
@@ -61,10 +74,21 @@ llist_empty(struct llist_head *head)
return (head->first == NULL);
}
+#define llist_for_each_safe(pos, n, node) \
+ for ((pos) = (node); \
+ (pos) != NULL && \
+ ((n) = (pos)->next, pos); \
+ (pos) = (n))
+
#define llist_for_each_entry_safe(pos, n, node, member) \
for (pos = llist_entry((node), __typeof(*pos), member); \
pos != NULL && \
(n = llist_entry(pos->member.next, __typeof(*pos), member), pos); \
pos = n)
+#define llist_for_each_entry(pos, node, member) \
+ for ((pos) = llist_entry((node), __typeof(*(pos)), member); \
+ (pos) != NULL; \
+ (pos) = llist_entry((pos)->member.next, __typeof(*(pos)), member))
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/lockdep.h b/sys/dev/pci/drm/include/linux/lockdep.h
index a6407a1d645..afdb6216b3d 100644
--- a/sys/dev/pci/drm/include/linux/lockdep.h
+++ b/sys/dev/pci/drm/include/linux/lockdep.h
@@ -6,11 +6,30 @@
struct lock_class_key {
};
+struct pin_cookie {
+};
+
#define might_lock(lock)
+#define might_lock_nested(lock, subc)
#define lockdep_assert_held(lock) do { (void)(lock); } while(0)
+#define lockdep_assert_held_once(lock) do { (void)(lock); } while(0)
#define lock_acquire(lock, a, b, c, d, e, f)
-#define lock_release(lock, a, b)
+#define lock_release(lock, a)
#define lock_acquire_shared_recursive(lock, a, b, c, d)
#define lockdep_set_subclass(a, b)
+#define lockdep_unpin_lock(a, b)
+#define lockdep_set_class(a, b)
+#define lockdep_init_map(a, b, c, d)
+
+#define mutex_acquire(a, b, c, d)
+#define mutex_release(a, b)
+
+#define SINGLE_DEPTH_NESTING 0
+
+#define lockdep_pin_lock(lock) \
+({ \
+ struct pin_cookie pc = {}; \
+ pc; \
+})
#endif
diff --git a/sys/dev/pci/drm/include/linux/log2.h b/sys/dev/pci/drm/include/linux/log2.h
index 8351b473b1f..5dc08372cac 100644
--- a/sys/dev/pci/drm/include/linux/log2.h
+++ b/sys/dev/pci/drm/include/linux/log2.h
@@ -8,6 +8,8 @@
#define ilog2(x) ((sizeof(x) <= 4) ? (fls(x) - 1) : (flsl(x) - 1))
+int drm_order(unsigned long);
+
#define is_power_of_2(x) (((x) != 0) && (((x) - 1) & (x)) == 0)
#define order_base_2(x) drm_order(x)
diff --git a/sys/dev/pci/drm/include/linux/math64.h b/sys/dev/pci/drm/include/linux/math64.h
index 7ca4f3b5808..8cf96571e94 100644
--- a/sys/dev/pci/drm/include/linux/math64.h
+++ b/sys/dev/pci/drm/include/linux/math64.h
@@ -56,4 +56,21 @@ mul_u64_u32_div(uint64_t x, uint32_t y, uint32_t div)
return (x * y) / div;
}
+#define DIV64_U64_ROUND_UP(x, y) \
+({ \
+ uint64_t _t = (y); \
+ div64_u64((x) + _t - 1, _t); \
+})
+
+static inline uint64_t
+mul_u64_u32_shr(uint64_t x, uint32_t y, unsigned int shift)
+{
+ uint32_t hi, lo;
+ hi = x >> 32;
+ lo = x & 0xffffffff;
+
+ return (mul_u32_u32(lo, y) >> shift) +
+ (mul_u32_u32(hi, y) << (32 - shift));
+}
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/media-bus-format.h b/sys/dev/pci/drm/include/linux/media-bus-format.h
index e69de29bb2d..7ef55e928e4 100644
--- a/sys/dev/pci/drm/include/linux/media-bus-format.h
+++ b/sys/dev/pci/drm/include/linux/media-bus-format.h
@@ -0,0 +1,8 @@
+/* Public domain. */
+
+#ifndef _LINUX_MEDIA_BUS_FORMAT_H
+#define _LINUX_MEDIA_BUS_FORMAT_H
+
+#define MEDIA_BUS_FMT_FIXED 1
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/mempolicy.h b/sys/dev/pci/drm/include/linux/mempolicy.h
index e69de29bb2d..b987c99da44 100644
--- a/sys/dev/pci/drm/include/linux/mempolicy.h
+++ b/sys/dev/pci/drm/include/linux/mempolicy.h
@@ -0,0 +1,8 @@
+/* Public domain. */
+
+#ifndef _LINUX_MEMPOLICY_H
+#define _LINUX_MEMPOLICY_H
+
+#include <linux/pagemap.h>
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/mm.h b/sys/dev/pci/drm/include/linux/mm.h
index 59b269ae815..fbf230c309d 100644
--- a/sys/dev/pci/drm/include/linux/mm.h
+++ b/sys/dev/pci/drm/include/linux/mm.h
@@ -12,6 +12,7 @@
#include <uvm/uvm_extern.h>
#include <linux/fs.h>
#include <linux/shrinker.h>
+#include <linux/overflow.h>
#include <asm/pgtable.h>
#define PageHighMem(x) 0
@@ -21,13 +22,14 @@
#define page_to_pfn(pp) (VM_PAGE_TO_PHYS(pp) / PAGE_SIZE)
#define pfn_to_page(pfn) (PHYS_TO_VM_PAGE(ptoa(pfn)))
#define nth_page(page, n) (&(page)[(n)])
-#define offset_in_page(off) ((off) & PAGE_MASK)
+#define offset_in_page(off) ((vaddr_t)(off) & PAGE_MASK)
#define set_page_dirty(page) atomic_clearbits_int(&page->pg_flags, PG_CLEAN)
#define PAGE_ALIGN(addr) (((addr) + PAGE_MASK) & ~PAGE_MASK)
#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
+#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
#define is_vmalloc_addr(ptr) true
diff --git a/sys/dev/pci/drm/include/linux/mm_types.h b/sys/dev/pci/drm/include/linux/mm_types.h
index e69de29bb2d..1fdd4c1b088 100644
--- a/sys/dev/pci/drm/include/linux/mm_types.h
+++ b/sys/dev/pci/drm/include/linux/mm_types.h
@@ -0,0 +1,11 @@
+/* Public domain. */
+
+#ifndef _LINUX_MM_TYPES_H
+#define _LINUX_MM_TYPES_H
+
+#include <linux/workqueue.h>
+#include <linux/completion.h>
+
+#include <uvm/uvm_extern.h>
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/mmzone.h b/sys/dev/pci/drm/include/linux/mmzone.h
new file mode 100644
index 00000000000..f373e2e5896
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/mmzone.h
@@ -0,0 +1,8 @@
+/* Public domain. */
+
+#ifndef _LINUX_MMZONE_H
+#define _LINUX_MMZONE_H
+
+#include <linux/mm_types.h>
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/mod_devicetable.h b/sys/dev/pci/drm/include/linux/mod_devicetable.h
index 173f3107763..847aaa85cf8 100644
--- a/sys/dev/pci/drm/include/linux/mod_devicetable.h
+++ b/sys/dev/pci/drm/include/linux/mod_devicetable.h
@@ -40,4 +40,14 @@ struct dmi_system_id {
#define DMI_MATCH(a, b) {(a), (b)}
#define DMI_EXACT_MATCH(a, b) {(a), (b)}
+struct pci_device_id {
+ uint16_t vendor;
+ uint16_t device;
+ uint16_t subvendor;
+ uint16_t subdevice;
+ uint32_t class;
+ uint32_t class_mask;
+ unsigned long driver_data;
+};
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/module.h b/sys/dev/pci/drm/include/linux/module.h
index 416077c072c..d976306e3de 100644
--- a/sys/dev/pci/drm/include/linux/module.h
+++ b/sys/dev/pci/drm/include/linux/module.h
@@ -5,6 +5,7 @@
#include <linux/export.h>
#include <linux/moduleparam.h>
+#include <linux/kobject.h>
struct module;
@@ -17,4 +18,15 @@ struct module;
#define module_exit(x)
#define symbol_put(x)
+static inline bool
+try_module_get(struct module *m)
+{
+ return true;
+}
+
+static inline void
+module_put(struct module *m)
+{
+}
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/moduleparam.h b/sys/dev/pci/drm/include/linux/moduleparam.h
index c94fe7b45ad..7785f976fce 100644
--- a/sys/dev/pci/drm/include/linux/moduleparam.h
+++ b/sys/dev/pci/drm/include/linux/moduleparam.h
@@ -8,5 +8,6 @@
#define module_param_named(name, value, type, perm)
#define module_param_named_unsafe(name, value, type, perm)
#define module_param_unsafe(name, type, perm)
+#define module_param_string(name, string, len, perm)
#endif
diff --git a/sys/dev/pci/drm/include/linux/mutex.h b/sys/dev/pci/drm/include/linux/mutex.h
index a1436f82228..5910b9743c0 100644
--- a/sys/dev/pci/drm/include/linux/mutex.h
+++ b/sys/dev/pci/drm/include/linux/mutex.h
@@ -11,6 +11,8 @@
#define DEFINE_MUTEX(x) struct rwlock x
#define mutex_lock_interruptible(rwl) -rw_enter(rwl, RW_WRITE | RW_INTR)
+#define mutex_lock_interruptible_nested(rwl, subc) \
+ -rw_enter(rwl, RW_WRITE | RW_INTR)
#define mutex_lock(rwl) rw_enter_write(rwl)
#define mutex_lock_nest_lock(rwl, sub) rw_enter_write(rwl)
#define mutex_lock_nested(rwl, sub) rw_enter_write(rwl)
@@ -35,4 +37,6 @@ mutex_trylock_recursive(struct rwlock *rwl)
return MUTEX_TRYLOCK_FAILED;
}
+int atomic_dec_and_mutex_lock(volatile int *, struct rwlock *);
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/nmi.h b/sys/dev/pci/drm/include/linux/nmi.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/nmi.h
diff --git a/sys/dev/pci/drm/include/linux/of.h b/sys/dev/pci/drm/include/linux/of.h
new file mode 100644
index 00000000000..cbac3f60606
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/of.h
@@ -0,0 +1,15 @@
+/* Public domain. */
+
+#ifndef _LINUX_OF_H
+#define _LINUX_OF_H
+
+#ifdef __macppc__
+static inline int
+of_machine_is_compatible(const char *model)
+{
+ extern char *hw_prod;
+ return (strcmp(model, hw_prod) == 0);
+}
+#endif
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/overflow.h b/sys/dev/pci/drm/include/linux/overflow.h
index ea8fa45e399..93615be569b 100644
--- a/sys/dev/pci/drm/include/linux/overflow.h
+++ b/sys/dev/pci/drm/include/linux/overflow.h
@@ -5,4 +5,7 @@
#define array_size(x, y) ((x) * (y))
+#define struct_size(p, member, n) \
+ (sizeof(*(p)) + ((n) * (sizeof(*(p)->member))))
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/pagemap.h b/sys/dev/pci/drm/include/linux/pagemap.h
index e69de29bb2d..92474a244f6 100644
--- a/sys/dev/pci/drm/include/linux/pagemap.h
+++ b/sys/dev/pci/drm/include/linux/pagemap.h
@@ -0,0 +1,9 @@
+/* Public domain. */
+
+#ifndef _LINUX_PAGEMAP_H
+#define _LINUX_PAGEMAP_H
+
+#include <linux/uaccess.h>
+#include <linux/highmem.h>
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/pci.h b/sys/dev/pci/drm/include/linux/pci.h
index 4ec8881f8ca..40348ececc0 100644
--- a/sys/dev/pci/drm/include/linux/pci.h
+++ b/sys/dev/pci/drm/include/linux/pci.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci.h,v 1.4 2019/08/28 10:17:59 kettenis Exp $ */
+/* $OpenBSD: pci.h,v 1.5 2020/06/08 04:48:15 jsg Exp $ */
/*
* Copyright (c) 2015 Mark Kettenis
*
@@ -19,22 +19,27 @@
#define _LINUX_PCI_H
#include <sys/types.h>
-#include <dev/pci/pcireg.h>
-#include <dev/pci/pcivar.h>
/* sparc64 cpu.h needs time.h and siginfo.h (indirect via param.h) */
#include <sys/param.h>
#include <machine/cpu.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
#include <uvm/uvm_extern.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/kobject.h>
+#include <linux/dma-mapping.h> /* pci-dma-compat.h -> dma-mapping.h */
+#include <linux/mod_devicetable.h>
struct pci_dev;
struct pci_bus {
pci_chipset_tag_t pc;
unsigned char number;
+ int domain_nr;
pcitag_t *bridgetag;
struct pci_dev *self;
};
@@ -66,6 +71,18 @@ struct pci_dev {
};
#define PCI_ANY_ID (uint16_t) (~0U)
+#ifndef PCI_MEM_START
+#define PCI_MEM_START 0
+#endif
+
+#ifndef PCI_MEM_END
+#define PCI_MEM_END 0xffffffff
+#endif
+
+#ifndef PCI_MEM64_END
+#define PCI_MEM64_END 0xffffffffffffffff
+#endif
+
#define PCI_VENDOR_ID_APPLE PCI_VENDOR_APPLE
#define PCI_VENDOR_ID_ASUSTEK PCI_VENDOR_ASUSTEK
#define PCI_VENDOR_ID_ATI PCI_VENDOR_ATI
@@ -95,6 +112,12 @@ struct pci_dev {
#define PCI_EXP_LNKCTL 0x10
#define PCI_EXP_LNKCTL_HAWD 0x0200
#define PCI_EXP_LNKCTL2 0x30
+#define PCI_EXP_LNKCTL2_ENTER_COMP 0x0010
+#define PCI_EXP_LNKCTL2_TX_MARGIN 0x0380
+#define PCI_EXP_LNKCTL2_TLS PCI_PCIE_LCSR2_TLS
+#define PCI_EXP_LNKCTL2_TLS_2_5GT PCI_PCIE_LCSR2_TLS_2_5
+#define PCI_EXP_LNKCTL2_TLS_5_0GT PCI_PCIE_LCSR2_TLS_5
+#define PCI_EXP_LNKCTL2_TLS_8_0GT PCI_PCIE_LCSR2_TLS_8
#define PCI_COMMAND PCI_COMMAND_STATUS_REG
#define PCI_COMMAND_MEMORY PCI_COMMAND_MEM_ENABLE
@@ -209,6 +232,12 @@ pci_pcie_cap(struct pci_dev *pdev)
}
static inline bool
+pci_is_pcie(struct pci_dev *pdev)
+{
+ return (pci_pcie_cap(pdev) > 0);
+}
+
+static inline bool
pci_is_root_bus(struct pci_bus *pbus)
{
return (pbus->bridgetag == NULL);
@@ -227,6 +256,51 @@ pcie_capability_read_dword(struct pci_dev *pdev, int off, u32 *val)
return 0;
}
+static inline int
+pcie_capability_read_word(struct pci_dev *pdev, int off, u16 *val)
+{
+ int pos;
+ if (!pci_get_capability(pdev->pc, pdev->tag, PCI_CAP_PCIEXPRESS,
+ &pos, NULL)) {
+ *val = 0;
+ return -EINVAL;
+ }
+ pci_read_config_word(pdev, pos + off, val);
+ return 0;
+}
+
+static inline int
+pcie_capability_write_word(struct pci_dev *pdev, int off, u16 val)
+{
+ int pos;
+ if (!pci_get_capability(pdev->pc, pdev->tag, PCI_CAP_PCIEXPRESS,
+ &pos, NULL))
+ return -EINVAL;
+ pci_write_config_word(pdev, pos + off, val);
+ return 0;
+}
+
+static inline int
+pcie_get_readrq(struct pci_dev *pdev)
+{
+ uint16_t val;
+
+ pcie_capability_read_word(pdev, PCI_PCIE_DCSR, &val);
+
+ return 128 << ((val & PCI_PCIE_DCSR_MPS) >> 12);
+}
+
+static inline int
+pcie_set_readrq(struct pci_dev *pdev, int rrq)
+{
+ uint16_t val;
+
+ pcie_capability_read_word(pdev, PCI_PCIE_DCSR, &val);
+ val &= ~PCI_PCIE_DCSR_MPS;
+ val |= (ffs(rrq) - 8) << 12;
+ return pcie_capability_write_word(pdev, PCI_PCIE_DCSR, val);
+}
+
#define pci_set_master(x)
#define pci_clear_master(x)
@@ -267,6 +341,20 @@ enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *);
enum pcie_link_width pcie_get_width_cap(struct pci_dev *);
int pci_resize_resource(struct pci_dev *, int, int);
+static inline void
+pcie_bandwidth_available(struct pci_dev *pdev, struct pci_dev **ldev,
+ enum pci_bus_speed *speed, enum pcie_link_width *width)
+{
+ struct pci_dev *bdev = pdev->bus->self;
+ if (bdev == NULL)
+ return;
+
+ if (speed)
+ *speed = pcie_get_speed_cap(bdev);
+ if (width)
+ *width = pcie_get_width_cap(bdev);
+}
+
#define pci_save_state(x)
#define pci_enable_device(x) 0
#define pci_disable_device(x)
@@ -274,6 +362,23 @@ int pci_resize_resource(struct pci_dev *, int, int);
#define pci_set_drvdata(x, y)
static inline int
+pci_domain_nr(struct pci_bus *pbus)
+{
+ return pbus->domain_nr;
+}
+
+static inline int
+pci_irq_vector(struct pci_dev *pdev, unsigned int num)
+{
+ return pdev->irq;
+}
+
+static inline void
+pci_free_irq_vectors(struct pci_dev *pdev)
+{
+}
+
+static inline int
pci_set_power_state(struct pci_dev *dev, int state)
{
return 0;
diff --git a/sys/dev/pci/drm/include/linux/perf_event.h b/sys/dev/pci/drm/include/linux/perf_event.h
index 935fd59b5fb..0f2e67e6542 100644
--- a/sys/dev/pci/drm/include/linux/perf_event.h
+++ b/sys/dev/pci/drm/include/linux/perf_event.h
@@ -3,6 +3,8 @@
#ifndef _LINUX_PERF_EVENT_H
#define _LINUX_PERF_EVENT_H
+#include <linux/ftrace.h>
+
struct pmu {
};
diff --git a/sys/dev/pci/drm/include/linux/pfn.h b/sys/dev/pci/drm/include/linux/pfn.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/pfn.h
diff --git a/sys/dev/pci/drm/include/linux/pid.h b/sys/dev/pci/drm/include/linux/pid.h
index 5aa09ef5322..8534accfad3 100644
--- a/sys/dev/pci/drm/include/linux/pid.h
+++ b/sys/dev/pci/drm/include/linux/pid.h
@@ -3,6 +3,8 @@
#ifndef _LINUX_PID_H
#define _LINUX_PID_H
+#include <linux/rculist.h>
+
#define put_pid(x)
#endif
diff --git a/sys/dev/pci/drm/include/linux/pm.h b/sys/dev/pci/drm/include/linux/pm.h
index 35c166bf79f..ac202674c7b 100644
--- a/sys/dev/pci/drm/include/linux/pm.h
+++ b/sys/dev/pci/drm/include/linux/pm.h
@@ -8,4 +8,7 @@
struct dev_pm_domain {
};
+typedef struct {
+} pm_message_t;
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/pm_qos.h b/sys/dev/pci/drm/include/linux/pm_qos.h
index 2a4e938b757..e4bc138a903 100644
--- a/sys/dev/pci/drm/include/linux/pm_qos.h
+++ b/sys/dev/pci/drm/include/linux/pm_qos.h
@@ -14,4 +14,8 @@ struct pm_qos_request {
#define pm_qos_add_request(a, b, c)
#define pm_qos_remove_request(a)
+#define cpu_latency_qos_update_request(a, b)
+#define cpu_latency_qos_add_request(a, b)
+#define cpu_latency_qos_remove_request(a)
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/pm_runtime.h b/sys/dev/pci/drm/include/linux/pm_runtime.h
index efbcfaa86bb..c692fcec1b3 100644
--- a/sys/dev/pci/drm/include/linux/pm_runtime.h
+++ b/sys/dev/pci/drm/include/linux/pm_runtime.h
@@ -9,6 +9,7 @@
#define pm_runtime_mark_last_busy(x)
#define pm_runtime_use_autosuspend(x)
+#define pm_runtime_dont_use_autosuspend(x)
#define pm_runtime_put_autosuspend(x)
#define pm_runtime_set_autosuspend_delay(x, y)
#define pm_runtime_set_active(x)
@@ -16,6 +17,7 @@
#define pm_runtime_put_noidle(x)
#define pm_runtime_forbid(x)
#define pm_runtime_get_noresume(x)
+#define pm_runtime_put(x)
static inline int
pm_runtime_get_sync(struct device *dev)
@@ -23,4 +25,10 @@ pm_runtime_get_sync(struct device *dev)
return 0;
}
+static inline int
+pm_runtime_get_if_in_use(struct device *dev)
+{
+ return -EINVAL;
+}
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/poison.h b/sys/dev/pci/drm/include/linux/poison.h
new file mode 100644
index 00000000000..35ccb5b5499
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/poison.h
@@ -0,0 +1,9 @@
+/* Public domain. */
+
+#ifndef _LINUX_POISON_H
+#define _LINUX_POISON_H
+
+#define POISON_INUSE 0xdb
+#define POISON_FREE 0xdf
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/poll.h b/sys/dev/pci/drm/include/linux/poll.h
index 1ba9509bba9..4998990d29c 100644
--- a/sys/dev/pci/drm/include/linux/poll.h
+++ b/sys/dev/pci/drm/include/linux/poll.h
@@ -4,5 +4,6 @@
#define _LINUX_POLL_H
#include <linux/ktime.h>
+#include <linux/uaccess.h>
#endif
diff --git a/sys/dev/pci/drm/include/linux/preempt.h b/sys/dev/pci/drm/include/linux/preempt.h
index c0d8bf6b95d..fdcaf207999 100644
--- a/sys/dev/pci/drm/include/linux/preempt.h
+++ b/sys/dev/pci/drm/include/linux/preempt.h
@@ -3,6 +3,8 @@
#ifndef _LINUX_PREEMPT_H
#define _LINUX_PREEMPT_H
+#include <asm/preempt.h>
+
#define preempt_enable()
#define preempt_disable()
@@ -19,5 +21,6 @@ in_irq(void)
#define in_interrupt() in_irq()
#define in_task() (!in_irq())
+#define in_atomic() 0
#endif
diff --git a/sys/dev/pci/drm/include/linux/prime_numbers.h b/sys/dev/pci/drm/include/linux/prime_numbers.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/prime_numbers.h
diff --git a/sys/dev/pci/drm/include/linux/printk.h b/sys/dev/pci/drm/include/linux/printk.h
index 854cdfb6598..e7fc370f11e 100644
--- a/sys/dev/pci/drm/include/linux/printk.h
+++ b/sys/dev/pci/drm/include/linux/printk.h
@@ -7,12 +7,16 @@
#include <sys/systm.h>
#include <sys/stdarg.h>
-#define KERN_INFO ""
-#define KERN_WARNING ""
-#define KERN_NOTICE ""
-#define KERN_DEBUG ""
-#define KERN_CRIT ""
-#define KERN_ERR ""
+#include <linux/init.h>
+
+#define KERN_CRIT "\0012"
+#define KERN_ERR "\0013"
+#define KERN_WARNING "\0014"
+#define KERN_NOTICE "\0015"
+#define KERN_INFO "\0016"
+#define KERN_DEBUG "\0017"
+
+#define KERN_CONT "\001c"
#ifndef pr_fmt
#define pr_fmt(fmt) fmt
@@ -21,25 +25,32 @@
#define printk_once(fmt, arg...) ({ \
static int __warned; \
if (!__warned) { \
- printf(fmt, ## arg); \
+ printk(fmt, ## arg); \
__warned = 1; \
} \
})
-#define printk(fmt, arg...) printf(fmt, ## arg)
-#define pr_warn(fmt, arg...) printf(pr_fmt(fmt), ## arg)
-#define pr_warn_once(fmt, arg...) printk_once(pr_fmt(fmt), ## arg)
-#define pr_notice(fmt, arg...) printf(pr_fmt(fmt), ## arg)
-#define pr_crit(fmt, arg...) printf(pr_fmt(fmt), ## arg)
-#define pr_err(fmt, arg...) printf(pr_fmt(fmt), ## arg)
-#define pr_cont(fmt, arg...) printf(pr_fmt(fmt), ## arg)
+#define printk_ratelimit() 1
+
+int printk(const char *fmt, ...);
+
+#define pr_warn(fmt, arg...) printk(KERN_WARNING pr_fmt(fmt), ## arg)
+#define pr_warn_ratelimited(fmt, arg...) printk(KERN_WARNING pr_fmt(fmt), ## arg)
+#define pr_warn_once(fmt, arg...) printk_once(KERN_WARNING pr_fmt(fmt), ## arg)
+#define pr_notice(fmt, arg...) printk(KERN_NOTICE pr_fmt(fmt), ## arg)
+#define pr_crit(fmt, arg...) printk(KERN_CRIT pr_fmt(fmt), ## arg)
+#define pr_err(fmt, arg...) printk(KERN_ERR pr_fmt(fmt), ## arg)
+#define pr_err_once(fmt, arg...) printk_once(KERN_ERR pr_fmt(fmt), ## arg)
+#define pr_cont(fmt, arg...) printk(KERN_CONT pr_fmt(fmt), ## arg)
#ifdef DRMDEBUG
-#define pr_info(fmt, arg...) printf(pr_fmt(fmt), ## arg)
-#define pr_info_once(fmt, arg...) printk_once(pr_fmt(fmt), ## arg)
-#define pr_debug(fmt, arg...) printf(pr_fmt(fmt), ## arg)
+#define pr_info(fmt, arg...) printk(KERN_INFO pr_fmt(fmt), ## arg)
+#define pr_info_ratelimited(fmt, arg...) printk(KERN_INFO pr_fmt(fmt), ## arg)
+#define pr_info_once(fmt, arg...) printk_once(KERN_INFO pr_fmt(fmt), ## arg)
+#define pr_debug(fmt, arg...) printk(KERN_DEBUG pr_fmt(fmt), ## arg)
#else
#define pr_info(fmt, arg...) do { } while(0)
+#define pr_info_ratelimited(fmt, arg...) do { } while(0)
#define pr_info_once(fmt, arg...) do { } while(0)
#define pr_debug(fmt, arg...) do { } while(0)
#endif
diff --git a/sys/dev/pci/drm/include/linux/pseudo_fs.h b/sys/dev/pci/drm/include/linux/pseudo_fs.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/pseudo_fs.h
diff --git a/sys/dev/pci/drm/include/linux/radix-tree.h b/sys/dev/pci/drm/include/linux/radix-tree.h
index 104ebafbe9f..e656a7711c9 100644
--- a/sys/dev/pci/drm/include/linux/radix-tree.h
+++ b/sys/dev/pci/drm/include/linux/radix-tree.h
@@ -32,6 +32,7 @@
#define _LINUX_RADIX_TREE_H_
#include <linux/types.h>
+#include <linux/xarray.h>
#define RADIX_TREE_MAP_SHIFT 6
#define RADIX_TREE_MAP_SIZE (1UL << RADIX_TREE_MAP_SHIFT)
diff --git a/sys/dev/pci/drm/include/linux/random.h b/sys/dev/pci/drm/include/linux/random.h
index 17d3611c862..23286b18fdb 100644
--- a/sys/dev/pci/drm/include/linux/random.h
+++ b/sys/dev/pci/drm/include/linux/random.h
@@ -27,4 +27,10 @@ get_random_long(void)
#endif
}
+static inline uint32_t
+prandom_u32_max(uint32_t x)
+{
+ return arc4random_uniform(x + 1);
+}
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/rbtree.h b/sys/dev/pci/drm/include/linux/rbtree.h
index b221ac7a56d..fe45a4eeeb1 100644
--- a/sys/dev/pci/drm/include/linux/rbtree.h
+++ b/sys/dev/pci/drm/include/linux/rbtree.h
@@ -50,7 +50,7 @@ struct rb_root {
};
struct rb_root_cached {
- struct rb_node *rb_node;
+ struct rb_root rb_root;
};
/*
@@ -77,18 +77,19 @@ RB_PROTOTYPE(linux_root, rb_node, __entry, panic_cmp);
#define rb_insert_color(node, root) \
linux_root_RB_INSERT_COLOR((struct linux_root *)(root), (node))
-#define rb_insert_color_cached(node, root, leftmost) \
- linux_root_RB_INSERT_COLOR((struct linux_root *)(root), (node))
#define rb_erase(node, root) \
linux_root_RB_REMOVE((struct linux_root *)(root), (node))
-#define rb_erase_cached(node, root) \
- linux_root_RB_REMOVE((struct linux_root *)(root), (node))
#define rb_next(node) RB_NEXT(linux_root, NULL, (node))
#define rb_prev(node) RB_PREV(linux_root, NULL, (node))
#define rb_first(root) RB_MIN(linux_root, (struct linux_root *)(root))
-#define rb_first_cached(root) RB_MIN(linux_root, (struct linux_root *)(root))
#define rb_last(root) RB_MAX(linux_root, (struct linux_root *)(root))
+#define rb_insert_color_cached(node, root, leftmost) \
+ linux_root_RB_INSERT_COLOR((struct linux_root *)(&(root)->rb_root), (node))
+#define rb_erase_cached(node, root) \
+ linux_root_RB_REMOVE((struct linux_root *)(&(root)->rb_root), (node))
+#define rb_first_cached(root) RB_MIN(linux_root, (struct linux_root *)(&(root)->rb_root))
+
static inline struct rb_node *
__rb_deepest_left(struct rb_node *node)
{
@@ -156,7 +157,11 @@ rb_replace_node(struct rb_node *victim, struct rb_node *new,
#undef RB_ROOT
#define RB_ROOT (struct rb_root) { NULL }
+#ifdef __clang__
#define RB_ROOT_CACHED (struct rb_root_cached) { NULL }
+#else
+#define RB_ROOT_CACHED (struct rb_root_cached) { { NULL } }
+#endif
struct interval_tree_node {
struct rb_node rb;
@@ -165,7 +170,7 @@ struct interval_tree_node {
};
static inline struct interval_tree_node *
-interval_tree_iter_first(struct rb_root *root,
+interval_tree_iter_first(struct rb_root_cached *root,
unsigned long start, unsigned long last)
{
#ifdef DRMDEBUG
@@ -175,7 +180,7 @@ interval_tree_iter_first(struct rb_root *root,
}
static inline void
-interval_tree_insert(struct interval_tree_node *node, struct rb_root *root)
+interval_tree_insert(struct interval_tree_node *node, struct rb_root_cached *root)
{
#ifdef DRMDEBUG
printf("%s: stub start: 0x%lx last: 0x%lx\n", __func__, node->start, node->last);
@@ -183,7 +188,7 @@ interval_tree_insert(struct interval_tree_node *node, struct rb_root *root)
}
static inline void
-interval_tree_remove(struct interval_tree_node *node, struct rb_root *root)
+interval_tree_remove(struct interval_tree_node *node, struct rb_root_cached *root)
{
#ifdef DRMDEBUG
printf("%s: stub start: 0x%lx last: 0x%lx\n", __func__, node->start, node->last);
diff --git a/sys/dev/pci/drm/include/linux/rculist.h b/sys/dev/pci/drm/include/linux/rculist.h
new file mode 100644
index 00000000000..537d6dbf9f9
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/rculist.h
@@ -0,0 +1,15 @@
+/* Public domain. */
+
+#ifndef _LINUX_RCULIST_H
+#define _LINUX_RCULIST_H
+
+#include <linux/list.h>
+#include <linux/rcupdate.h>
+
+#define list_add_rcu(a, b) list_add(a, b)
+#define list_add_tail_rcu(a, b) list_add_tail(a, b)
+#define list_del_rcu(a) list_del(a)
+#define list_for_each_entry_rcu list_for_each_entry
+#define list_for_each_entry_lockless(a, b, c) list_for_each_entry(a, b, c)
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/rcupdate.h b/sys/dev/pci/drm/include/linux/rcupdate.h
index 3bb821befcf..346c87e862a 100644
--- a/sys/dev/pci/drm/include/linux/rcupdate.h
+++ b/sys/dev/pci/drm/include/linux/rcupdate.h
@@ -18,6 +18,15 @@ struct rcu_head {
#define rcu_read_lock()
#define rcu_read_unlock()
#define rcu_pointer_handoff(p) (p)
+#define init_rcu_head(h)
+#define destroy_rcu_head(h)
+
+#define rcu_replace_pointer(rp, p, c) \
+({ \
+ __typeof(rp) __r = rp; \
+ rp = p; \
+ __r; \
+})
#define kfree_rcu(objp, name) do { free((void *)objp, M_DRM, 0); } while(0)
@@ -32,5 +41,8 @@ call_rcu(struct rcu_head *head, void (*fn)(struct rcu_head *))
}
#define synchronize_rcu()
+#define synchronize_rcu_expedited()
+#define cond_synchronize_rcu(x)
+#define get_state_synchronize_rcu() 0
#endif
diff --git a/sys/dev/pci/drm/include/linux/refcount.h b/sys/dev/pci/drm/include/linux/refcount.h
index 402a985406e..fea109c5f06 100644
--- a/sys/dev/pci/drm/include/linux/refcount.h
+++ b/sys/dev/pci/drm/include/linux/refcount.h
@@ -6,10 +6,38 @@
#include <sys/types.h>
#include <linux/atomic.h>
+typedef atomic_t refcount_t;
+
static inline bool
refcount_dec_and_test(uint32_t *p)
{
return atomic_dec_and_test(p);
}
+static inline bool
+refcount_inc_not_zero(uint32_t *p)
+{
+ return atomic_inc_not_zero(p);
+}
+
+static inline void
+refcount_set(uint32_t *p, int v)
+{
+ atomic_set(p, v);
+}
+
+static inline bool
+refcount_dec_and_lock_irqsave(volatile int *v, struct mutex *lock,
+ unsigned long *flags)
+{
+ if (atomic_add_unless(v, -1, 1))
+ return false;
+
+ mtx_enter(lock);
+ if (atomic_dec_return(v) == 0)
+ return true;
+ mtx_leave(lock);
+ return false;
+}
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/rwsem.h b/sys/dev/pci/drm/include/linux/rwsem.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/rwsem.h
diff --git a/sys/dev/pci/drm/include/linux/scatterlist.h b/sys/dev/pci/drm/include/linux/scatterlist.h
index 4ec58c80de0..effe1ce499b 100644
--- a/sys/dev/pci/drm/include/linux/scatterlist.h
+++ b/sys/dev/pci/drm/include/linux/scatterlist.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: scatterlist.h,v 1.1 2019/04/14 10:14:53 jsg Exp $ */
+/* $OpenBSD: scatterlist.h,v 1.2 2020/06/08 04:48:15 jsg Exp $ */
/*
* Copyright (c) 2013, 2014, 2015 Mark Kettenis
*
@@ -22,7 +22,10 @@
#include <sys/param.h>
#include <uvm/uvm_extern.h>
+#include <linux/mm.h>
+
struct scatterlist {
+ struct vm_page *__page;
dma_addr_t dma_address;
unsigned int offset;
unsigned int length;
@@ -98,13 +101,20 @@ sg_page_iter_page(struct sg_page_iter *iter)
static inline struct vm_page *
sg_page(struct scatterlist *sgl)
{
- return PHYS_TO_VM_PAGE(sgl->dma_address);
+ return sgl->__page;
+}
+
+static inline void
+sg_assign_page(struct scatterlist *sgl, struct vm_page *page)
+{
+ sgl->__page = page;
}
static inline void
sg_set_page(struct scatterlist *sgl, struct vm_page *page,
unsigned int length, unsigned int offset)
{
+ sgl->__page = page;
sgl->dma_address = VM_PAGE_TO_PHYS(page);
sgl->offset = offset;
sgl->length = length;
diff --git a/sys/dev/pci/drm/include/linux/sched.h b/sys/dev/pci/drm/include/linux/sched.h
index 9def4c4be27..95f074795b1 100644
--- a/sys/dev/pci/drm/include/linux/sched.h
+++ b/sys/dev/pci/drm/include/linux/sched.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sched.h,v 1.2 2020/02/18 12:13:40 mpi Exp $ */
+/* $OpenBSD: sched.h,v 1.3 2020/06/08 04:48:15 jsg Exp $ */
/*
* Copyright (c) 2013, 2014, 2015 Mark Kettenis
*
@@ -25,6 +25,7 @@
#include <sys/mutex.h>
#include <linux/wait.h>
#include <linux/hrtimer.h>
+#include <linux/sem.h>
#define TASK_NORMAL 1
#define TASK_UNINTERRUPTIBLE 0
@@ -43,6 +44,7 @@ void set_current_state(int);
void __set_current_state(int);
void schedule(void);
long schedule_timeout(long);
+long schedule_timeout_uninterruptible(long);
#define io_schedule_timeout(x) schedule_timeout(x)
diff --git a/sys/dev/pci/drm/include/linux/sched/clock.h b/sys/dev/pci/drm/include/linux/sched/clock.h
index 3604ee1ac17..efb3fc2bd00 100644
--- a/sys/dev/pci/drm/include/linux/sched/clock.h
+++ b/sys/dev/pci/drm/include/linux/sched/clock.h
@@ -4,8 +4,8 @@
#define _LINUX_SCHED_CLOCK_H
#include <sys/types.h>
-#include <sys/time.h>
+#include <linux/time.h>
#include <linux/smp.h>
static inline uint64_t
diff --git a/sys/dev/pci/drm/include/linux/sched/signal.h b/sys/dev/pci/drm/include/linux/sched/signal.h
index c201146f159..a405933671d 100644
--- a/sys/dev/pci/drm/include/linux/sched/signal.h
+++ b/sys/dev/pci/drm/include/linux/sched/signal.h
@@ -3,6 +3,7 @@
#ifndef _LINUX_SCHED_SIGNAL_H
#define _LINUX_SCHED_SIGNAL_H
+#include <sys/param.h>
#include <sys/systm.h>
#include <sys/signalvar.h>
diff --git a/sys/dev/pci/drm/include/linux/sched/task.h b/sys/dev/pci/drm/include/linux/sched/task.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/sched/task.h
diff --git a/sys/dev/pci/drm/include/linux/sem.h b/sys/dev/pci/drm/include/linux/sem.h
new file mode 100644
index 00000000000..6cca4ccef8d
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/sem.h
@@ -0,0 +1,8 @@
+/* Public domain. */
+
+#ifndef _LINUX_SEM_H
+#define _LINUX_SEM_H
+
+#include <linux/ipc.h> /* via uapi/linux/sem.h */
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/semaphore.h b/sys/dev/pci/drm/include/linux/semaphore.h
new file mode 100644
index 00000000000..f89bbb34443
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/semaphore.h
@@ -0,0 +1,9 @@
+/* Public domain. */
+
+#ifndef _LINUX_SEMAPHORE_H
+#define _LINUX_SEMAPHORE_H
+
+struct semaphore {
+};
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/shmem_fs.h b/sys/dev/pci/drm/include/linux/shmem_fs.h
index e69de29bb2d..c728c6d8489 100644
--- a/sys/dev/pci/drm/include/linux/shmem_fs.h
+++ b/sys/dev/pci/drm/include/linux/shmem_fs.h
@@ -0,0 +1,10 @@
+/* Public domain. */
+
+#ifndef _LINUX_SHMEM_FS_H
+#define _LINUX_SHMEM_FS_H
+
+#include <linux/mempolicy.h>
+#include <linux/swap.h>
+#include <linux/file.h>
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/sizes.h b/sys/dev/pci/drm/include/linux/sizes.h
index 01a1dc4a269..4d43eec763b 100644
--- a/sys/dev/pci/drm/include/linux/sizes.h
+++ b/sys/dev/pci/drm/include/linux/sizes.h
@@ -3,11 +3,17 @@
#ifndef _LINUX_SIZES_H
#define _LINUX_SIZES_H
+#define SZ_1K (1024 * 1)
#define SZ_4K (1024 * 4)
#define SZ_8K (1024 * 8)
+#define SZ_16K (1024 * 16)
#define SZ_32K (1024 * 32)
+#define SZ_64K (1024 * 64)
#define SZ_128K (1024 * 128)
-#define SZ_1M (1024 * 1024)
-#define SZ_16M (16 * 1024 * 1024)
+#define SZ_256K (1024 * 256)
+#define SZ_1M (1024 * 1024 * 1)
+#define SZ_2M (1024 * 1024 * 2)
+#define SZ_8M (1024 * 1024 * 8)
+#define SZ_16M (1024 * 1024 * 16)
#endif
diff --git a/sys/dev/pci/drm/include/linux/smp.h b/sys/dev/pci/drm/include/linux/smp.h
index 354bf92be3c..4db0fee69be 100644
--- a/sys/dev/pci/drm/include/linux/smp.h
+++ b/sys/dev/pci/drm/include/linux/smp.h
@@ -9,4 +9,7 @@
#define smp_processor_id() (curcpu()->ci_cpuid)
+#define get_cpu() cpu_number()
+#define put_cpu()
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/spinlock.h b/sys/dev/pci/drm/include/linux/spinlock.h
index e40d2872d00..8b1a437e9ae 100644
--- a/sys/dev/pci/drm/include/linux/spinlock.h
+++ b/sys/dev/pci/drm/include/linux/spinlock.h
@@ -7,6 +7,7 @@
#include <linux/spinlock_types.h>
#include <linux/preempt.h>
#include <linux/bottom_half.h>
+#include <linux/atomic.h>
#define spin_lock_irqsave(_mtxp, _flags) do { \
_flags = 0; \
@@ -24,6 +25,28 @@
mtx_leave(_mtxp); \
} while (0)
+#define spin_trylock_irqsave(_mtxp, _flags) \
+({ \
+ (void)(_flags); \
+ mtx_enter_try(_mtxp) ? 1 : 0; \
+})
+
+static inline int
+atomic_dec_and_lock(volatile int *v, struct mutex *mtxp)
+{
+ if (*v != 1) {
+ atomic_dec(v);
+ return 0;
+ }
+
+ mtx_enter(mtxp);
+ atomic_dec(v);
+ return 1;
+}
+
+#define atomic_dec_and_lock_irqsave(_a, _mtxp, _flags) \
+ atomic_dec_and_lock(_a, _mtxp)
+
#define spin_lock(mtxp) mtx_enter(mtxp)
#define spin_lock_nested(mtxp, l) mtx_enter(mtxp)
#define spin_unlock(mtxp) mtx_leave(mtxp)
diff --git a/sys/dev/pci/drm/include/linux/srcu.h b/sys/dev/pci/drm/include/linux/srcu.h
new file mode 100644
index 00000000000..dbabe2f8d6d
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/srcu.h
@@ -0,0 +1,14 @@
+/* Public domain. */
+
+#ifndef _LINUX_SRCU_H
+#define _LINUX_SRCU_H
+
+#define init_srcu_struct(x)
+#define cleanup_srcu_struct(x)
+
+#define srcu_read_lock(x) 0
+#define srcu_read_unlock(x, y)
+
+#define synchronize_srcu_expedited(x)
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/stackdepot.h b/sys/dev/pci/drm/include/linux/stackdepot.h
new file mode 100644
index 00000000000..2ae1c9b8d31
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/stackdepot.h
@@ -0,0 +1,8 @@
+/* Public domain. */
+
+#ifndef _LINUX_STACKDEPOT_H
+#define _LINUX_STACKDEPOT_H
+
+typedef uint32_t depot_stack_handle_t;
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/stacktrace.h b/sys/dev/pci/drm/include/linux/stacktrace.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/stacktrace.h
diff --git a/sys/dev/pci/drm/include/linux/stat.h b/sys/dev/pci/drm/include/linux/stat.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/stat.h
diff --git a/sys/dev/pci/drm/include/linux/string.h b/sys/dev/pci/drm/include/linux/string.h
index b77067b1bcc..dc45a038546 100644
--- a/sys/dev/pci/drm/include/linux/string.h
+++ b/sys/dev/pci/drm/include/linux/string.h
@@ -54,6 +54,9 @@ kstrdup(const char *str, int flags)
size_t len;
char *p;
+ if (str == NULL)
+ return NULL;
+
len = strlen(str) + 1;
p = malloc(len, M_DRM, flags);
if (p)
diff --git a/sys/dev/pci/drm/include/linux/suspend.h b/sys/dev/pci/drm/include/linux/suspend.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/suspend.h
diff --git a/sys/dev/pci/drm/include/linux/swap.h b/sys/dev/pci/drm/include/linux/swap.h
index ce2f8ad9378..d6c8202a5a5 100644
--- a/sys/dev/pci/drm/include/linux/swap.h
+++ b/sys/dev/pci/drm/include/linux/swap.h
@@ -3,6 +3,18 @@
#ifndef _LINUX_SWAP_H
#define _LINUX_SWAP_H
+/*
+ * normally clock.h would be indirectly included via
+ *
+ * linux/swap.h
+ * linux/memcontrol.h
+ * linux/writeback.h
+ * linux/blk-cgroup.h
+ * linux/blkdev.h
+ * linux/sched/clock.h
+ */
+#include <linux/sched/clock.h>
+
#include <uvm/uvm_extern.h>
static inline long
diff --git a/sys/dev/pci/drm/include/linux/syscalls.h b/sys/dev/pci/drm/include/linux/syscalls.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/syscalls.h
diff --git a/sys/dev/pci/drm/include/linux/sysfs.h b/sys/dev/pci/drm/include/linux/sysfs.h
index c9be9a48fba..409373609b0 100644
--- a/sys/dev/pci/drm/include/linux/sysfs.h
+++ b/sys/dev/pci/drm/include/linux/sysfs.h
@@ -3,9 +3,27 @@
#ifndef _LINUX_SYSFS_H
#define _LINUX_SYSFS_H
+#include <linux/kernfs.h>
+
+struct attribute {
+ const char *name;
+ int mode;
+};
+
+struct bin_attribute {
+};
+
+struct attribute_group {
+ const char *name;
+ struct attribute **attrs;
+ struct bin_attribute **bin_attrs;
+};
+
#define sysfs_create_link(x, y, z) 0
#define sysfs_remove_link(x, y)
#define sysfs_create_group(x, y) 0
#define sysfs_remove_group(x, y)
+#define sysfs_remove_file(x, y)
+#define sysfs_remove_file_from_group(x, y, z)
#endif
diff --git a/sys/dev/pci/drm/include/linux/sysrq.h b/sys/dev/pci/drm/include/linux/sysrq.h
index 1805e30387a..7cc51b6db6c 100644
--- a/sys/dev/pci/drm/include/linux/sysrq.h
+++ b/sys/dev/pci/drm/include/linux/sysrq.h
@@ -3,6 +3,19 @@
#ifndef _LINUX_SYSRQ_H
#define _LINUX_SYSRQ_H
-#define register_sysrq_key(x, y)
+struct sysrq_key_op {
+};
+
+static inline int
+register_sysrq_key(int k, struct sysrq_key_op *op)
+{
+ return 0;
+}
+
+static inline int
+unregister_sysrq_key(int k, struct sysrq_key_op *op)
+{
+ return 0;
+}
#endif
diff --git a/sys/dev/pci/drm/include/linux/thread_info.h b/sys/dev/pci/drm/include/linux/thread_info.h
new file mode 100644
index 00000000000..c64eb4ea1bd
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/thread_info.h
@@ -0,0 +1,8 @@
+/* Public domain. */
+
+#ifndef _LINUX_THREAD_INFO_H
+#define _LINUX_THREAD_INFO_H
+
+#include <asm/thread_info.h>
+
+#endif
diff --git a/sys/dev/pci/drm/include/linux/time.h b/sys/dev/pci/drm/include/linux/time.h
index c8a97b94b1a..0719b8fce65 100644
--- a/sys/dev/pci/drm/include/linux/time.h
+++ b/sys/dev/pci/drm/include/linux/time.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: time.h,v 1.1 2019/04/14 10:14:53 jsg Exp $ */
+/* $OpenBSD: time.h,v 1.2 2020/06/08 04:48:15 jsg Exp $ */
/*
* Copyright (c) 2013, 2014, 2015 Mark Kettenis
*
@@ -20,11 +20,15 @@
#include <sys/time.h>
#include <linux/math64.h>
+#include <linux/seqlock.h>
#define NSEC_PER_USEC 1000L
#define NSEC_PER_MSEC 1000000L
#define NSEC_PER_SEC 1000000000L
+#define USEC_PER_MSEC 1000L
+#define USEC_PER_SEC 1000000L
+
extern struct timespec ns_to_timespec(const int64_t);
extern int64_t timeval_to_ms(const struct timeval *);
extern int64_t timeval_to_ns(const struct timeval *);
diff --git a/sys/dev/pci/drm/include/linux/timekeeping.h b/sys/dev/pci/drm/include/linux/timekeeping.h
index fc27e921cd5..c6aa77583c7 100644
--- a/sys/dev/pci/drm/include/linux/timekeeping.h
+++ b/sys/dev/pci/drm/include/linux/timekeeping.h
@@ -18,4 +18,11 @@ ktime_get_real_seconds(void)
return ktime_get().tv_sec;
}
+static inline uint64_t
+ktime_get_ns(void)
+{
+ struct timeval tv = ktime_get();
+ return timeval_to_ns(&tv);
+}
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/timer.h b/sys/dev/pci/drm/include/linux/timer.h
index b1f11a2c916..a475ee10adb 100644
--- a/sys/dev/pci/drm/include/linux/timer.h
+++ b/sys/dev/pci/drm/include/linux/timer.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: timer.h,v 1.1 2019/04/14 10:14:53 jsg Exp $ */
+/* $OpenBSD: timer.h,v 1.2 2020/06/08 04:48:15 jsg Exp $ */
/*
* Copyright (c) 2013, 2014, 2015 Mark Kettenis
*
@@ -28,6 +28,7 @@
#define mod_timer(x, y) timeout_add((x), (y - jiffies))
#define mod_timer_pinned(x, y) timeout_add((x), (y - jiffies))
#define del_timer_sync(x) timeout_del((x))
+#define del_timer(x) timeout_del((x))
#define timer_pending(x) timeout_pending((x))
static inline unsigned long
diff --git a/sys/dev/pci/drm/include/linux/tracepoint.h b/sys/dev/pci/drm/include/linux/tracepoint.h
index a28216f65ac..750a63afc6b 100644
--- a/sys/dev/pci/drm/include/linux/tracepoint.h
+++ b/sys/dev/pci/drm/include/linux/tracepoint.h
@@ -3,6 +3,8 @@
#ifndef _LINUX_TRACEPOINT_H
#define _LINUX_TRACEPOINT_H
+#include <linux/types.h>
+
#define TP_PROTO(x...) x
#define DEFINE_EVENT(template, name, proto, args) \
diff --git a/sys/dev/pci/drm/include/linux/types.h b/sys/dev/pci/drm/include/linux/types.h
index 5ec2b85b594..bc9222ca2ee 100644
--- a/sys/dev/pci/drm/include/linux/types.h
+++ b/sys/dev/pci/drm/include/linux/types.h
@@ -34,6 +34,8 @@ typedef uint16_t __le16;
typedef uint16_t __be16;
typedef uint32_t __le32;
typedef uint32_t __be32;
+typedef uint64_t __le64;
+typedef uint64_t __be64;
typedef bus_addr_t dma_addr_t;
typedef bus_addr_t phys_addr_t;
diff --git a/sys/dev/pci/drm/include/linux/uaccess.h b/sys/dev/pci/drm/include/linux/uaccess.h
index 1a0325f7f78..459eadf0b21 100644
--- a/sys/dev/pci/drm/include/linux/uaccess.h
+++ b/sys/dev/pci/drm/include/linux/uaccess.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: uaccess.h,v 1.2 2019/12/18 08:56:19 kettenis Exp $ */
+/* $OpenBSD: uaccess.h,v 1.3 2020/06/08 04:48:15 jsg Exp $ */
/*
* Copyright (c) 2015 Mark Kettenis
*
@@ -22,9 +22,6 @@
#include <sys/systm.h>
#include <linux/sched.h>
-#define user_access_begin()
-#define user_access_end()
-
static inline unsigned long
__copy_to_user(void *to, const void *from, unsigned len)
{
@@ -70,11 +67,14 @@ copy_from_user(void *to, const void *from, unsigned len)
#define VERIFY_READ 0x1
#define VERIFY_WRITE 0x2
static inline int
-access_ok(int type, const void *addr, unsigned long size)
+access_ok(const void *addr, unsigned long size)
{
- return true;
+ return 1;
}
+#define user_access_begin(addr, size) access_ok(addr, size)
+#define user_access_end()
+
#if defined(__i386__) || defined(__amd64__)
static inline void
diff --git a/sys/dev/pci/drm/include/linux/uio.h b/sys/dev/pci/drm/include/linux/uio.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/uio.h
diff --git a/sys/dev/pci/drm/include/linux/utsname.h b/sys/dev/pci/drm/include/linux/utsname.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/utsname.h
diff --git a/sys/dev/pci/drm/include/linux/vga_switcheroo.h b/sys/dev/pci/drm/include/linux/vga_switcheroo.h
index ccdb11c5a97..30518e24cbb 100644
--- a/sys/dev/pci/drm/include/linux/vga_switcheroo.h
+++ b/sys/dev/pci/drm/include/linux/vga_switcheroo.h
@@ -3,15 +3,30 @@
#ifndef _LINUX_VGA_SWITCHEROO_H
#define _LINUX_VGA_SWITCHEROO_H
+#include <linux/fb.h>
+
+struct pci_dev;
+
#define vga_switcheroo_register_client(a, b, c) 0
#define vga_switcheroo_unregister_client(a)
#define vga_switcheroo_process_delayed_switch()
#define vga_switcheroo_fini_domain_pm_ops(x)
-#define vga_switcheroo_lock_ddc(x)
-#define vga_switcheroo_unlock_ddc(x)
#define vga_switcheroo_handler_flags() 0
#define vga_switcheroo_client_fb_set(a, b)
+#define vga_switcheroo_init_domain_pm_ops(a, b)
#define VGA_SWITCHEROO_CAN_SWITCH_DDC 1
+static inline int
+vga_switcheroo_lock_ddc(struct pci_dev *pdev)
+{
+ return -ENOSYS;
+}
+
+static inline int
+vga_switcheroo_unlock_ddc(struct pci_dev *pdev)
+{
+ return -ENOSYS;
+}
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/vgaarb.h b/sys/dev/pci/drm/include/linux/vgaarb.h
index 8a5721af5da..9f8ce34c1d4 100644
--- a/sys/dev/pci/drm/include/linux/vgaarb.h
+++ b/sys/dev/pci/drm/include/linux/vgaarb.h
@@ -18,4 +18,10 @@ vga_client_register(struct pci_dev *a, void *b, void *c, void *d)
return -ENODEV;
}
+static inline int
+vga_remove_vgacon(struct pci_dev *a)
+{
+ return 0;
+}
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/wait.h b/sys/dev/pci/drm/include/linux/wait.h
index 5860e906a5c..68a6e07ab7f 100644
--- a/sys/dev/pci/drm/include/linux/wait.h
+++ b/sys/dev/pci/drm/include/linux/wait.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: wait.h,v 1.4 2019/05/08 23:35:23 jsg Exp $ */
+/* $OpenBSD: wait.h,v 1.5 2020/06/08 04:48:15 jsg Exp $ */
/*
* Copyright (c) 2013, 2014, 2015 Mark Kettenis
* Copyright (c) 2017 Martin Pieuchot
@@ -147,10 +147,12 @@ do { \
} while (0)
#define wait_event_killable(wq, condition) \
-do { \
+({ \
+ int __ret = 0; \
if (!(condition)) \
- __wait_event_intr_timeout(wq, condition, 0, PCATCH); \
-} while (0)
+ __ret = __wait_event_intr_timeout(wq, condition, 0, PCATCH); \
+ __ret; \
+})
#define wait_event_interruptible(wq, condition) \
({ \
diff --git a/sys/dev/pci/drm/include/linux/wait_bit.h b/sys/dev/pci/drm/include/linux/wait_bit.h
index 6f30fdc1ede..2d91c8841b6 100644
--- a/sys/dev/pci/drm/include/linux/wait_bit.h
+++ b/sys/dev/pci/drm/include/linux/wait_bit.h
@@ -3,8 +3,27 @@
#ifndef _LINUX_WAIT_BIT_H
#define _LINUX_WAIT_BIT_H
+#include <linux/wait.h>
+
int wait_on_bit(unsigned long *, int, unsigned);
int wait_on_bit_timeout(unsigned long *, int, unsigned, int);
void wake_up_bit(void *, int);
+void clear_and_wake_up_bit(int, void *);
+
+wait_queue_head_t *bit_waitqueue(void *, int);
+
+extern wait_queue_head_t var_waitq;
+
+static inline void
+wake_up_var(void *var)
+{
+ wake_up(&var_waitq);
+}
+
+#define wait_var_event_interruptible(var, condition) \
+ wait_event_interruptible(var_waitq, condition)
+
+#define wait_var_event_killable(var, condition) \
+ wait_event_killable(var_waitq, condition)
#endif
diff --git a/sys/dev/pci/drm/include/linux/workqueue.h b/sys/dev/pci/drm/include/linux/workqueue.h
index 039a0ab9d2a..e2a877d2ab3 100644
--- a/sys/dev/pci/drm/include/linux/workqueue.h
+++ b/sys/dev/pci/drm/include/linux/workqueue.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: workqueue.h,v 1.2 2019/05/11 14:39:13 jsg Exp $ */
+/* $OpenBSD: workqueue.h,v 1.3 2020/06/08 04:48:15 jsg Exp $ */
/*
* Copyright (c) 2015 Mark Kettenis
*
@@ -32,6 +32,7 @@
struct workqueue_struct;
extern struct workqueue_struct *system_wq;
+extern struct workqueue_struct *system_highpri_wq;
extern struct workqueue_struct *system_unbound_wq;
extern struct workqueue_struct *system_long_wq;
@@ -39,6 +40,8 @@ extern struct workqueue_struct *system_long_wq;
#define WQ_FREEZABLE 2
#define WQ_UNBOUND 4
+#define WQ_UNBOUND_MAX_ACTIVE 4 /* matches nthreads in drm_linux.c */
+
static inline struct workqueue_struct *
alloc_workqueue(const char *name, int flags, int max_active)
{
@@ -195,4 +198,21 @@ bool flush_delayed_work(struct delayed_work *);
#define destroy_work_on_stack(x)
#define destroy_delayed_work_on_stack(x)
+struct rcu_work {
+ struct work_struct work;
+ struct rcu_head rcu;
+};
+
+static inline void
+INIT_RCU_WORK(struct rcu_work *work, work_func_t func)
+{
+ INIT_WORK(&work->work, func);
+}
+
+static inline bool
+queue_rcu_work(struct workqueue_struct *wq, struct rcu_work *work)
+{
+ return queue_work(wq, &work->work);
+}
+
#endif
diff --git a/sys/dev/pci/drm/include/linux/ww_mutex.h b/sys/dev/pci/drm/include/linux/ww_mutex.h
index a38780b8bd5..82018493a67 100644
--- a/sys/dev/pci/drm/include/linux/ww_mutex.h
+++ b/sys/dev/pci/drm/include/linux/ww_mutex.h
@@ -55,7 +55,7 @@ struct ww_acquire_ctx {
struct ww_mutex {
struct mutex base;
volatile int acquired;
- volatile struct ww_acquire_ctx *ctx;
+ struct ww_acquire_ctx *ctx;
volatile struct proc *owner;
};
diff --git a/sys/dev/pci/drm/include/linux/xarray.h b/sys/dev/pci/drm/include/linux/xarray.h
new file mode 100644
index 00000000000..6aa486be54b
--- /dev/null
+++ b/sys/dev/pci/drm/include/linux/xarray.h
@@ -0,0 +1,58 @@
+/* Public domain. */
+
+#ifndef _LINUX_XARRAY_H
+#define _LINUX_XARRAY_H
+
+#include <linux/gfp.h>
+
+#include <sys/tree.h>
+#include <sys/pool.h>
+
+#define XA_FLAGS_ALLOC 1
+#define XA_FLAGS_ALLOC1 2
+
+struct xarray_entry {
+ SPLAY_ENTRY(xarray_entry) entry;
+ int id;
+ void *ptr;
+};
+
+struct xarray {
+ gfp_t xa_flags;
+ SPLAY_HEAD(xarray_tree, xarray_entry) xa_tree;
+};
+
+void xa_init_flags(struct xarray *, gfp_t);
+void xa_destroy(struct xarray *);
+int xa_alloc(struct xarray *, u32 *, void *, int, gfp_t);
+void *xa_load(struct xarray *, unsigned long);
+void *xa_erase(struct xarray *, unsigned long);
+void *xa_get_next(struct xarray *, unsigned long *);
+
+#define xa_for_each(xa, index, entry) \
+ for (index = 0; ((entry) = xa_get_next(xa, &(index))) != NULL; index++)
+
+#define xa_limit_32b 0
+
+static inline void *
+xa_mk_value(unsigned long v)
+{
+ unsigned long r = (v << 1) | 1;
+ return (void *)r;
+}
+
+static inline bool
+xa_is_value(const void *e)
+{
+ unsigned long v = (unsigned long)e;
+ return v & 1;
+}
+
+static inline unsigned long
+xa_to_value(const void *e)
+{
+ unsigned long v = (unsigned long)e;
+ return v >> 1;
+}
+
+#endif
diff --git a/sys/dev/pci/drm/include/media/cec-notifier.h b/sys/dev/pci/drm/include/media/cec-notifier.h
index 6e0dca87875..8a1434606bb 100644
--- a/sys/dev/pci/drm/include/media/cec-notifier.h
+++ b/sys/dev/pci/drm/include/media/cec-notifier.h
@@ -3,9 +3,15 @@
#ifndef _MEDIA_CEC_NOTIFIER_H
#define _MEDIA_CEC_NOTIFIER_H
+struct cec_connector_info {
+};
+
#define cec_notifier_set_phys_addr_from_edid(x, y)
#define cec_notifier_phys_addr_invalidate(x)
#define cec_notifier_put(x)
#define cec_notifier_get_conn(x, y) NULL
+#define cec_fill_conn_info_from_drm(x, y)
+#define cec_notifier_conn_register(x, y, z) (void *)1
+#define cec_notifier_conn_unregister(x)
#endif
diff --git a/sys/dev/pci/drm/include/trace/define_trace.h b/sys/dev/pci/drm/include/trace/define_trace.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sys/dev/pci/drm/include/trace/define_trace.h
diff --git a/sys/dev/pci/drm/include/trace/events/dma_fence.h b/sys/dev/pci/drm/include/trace/events/dma_fence.h
new file mode 100644
index 00000000000..da32d160f3e
--- /dev/null
+++ b/sys/dev/pci/drm/include/trace/events/dma_fence.h
@@ -0,0 +1,14 @@
+/* Public domain. */
+
+#ifndef _TRACE_EVENTS_DMA_FENCE_H
+#define _TRACE_EVENTS_DMA_FENCE_H
+
+#define trace_dma_fence_destroy(a)
+#define trace_dma_fence_emit(a)
+#define trace_dma_fence_enable_signal(a)
+#define trace_dma_fence_init(a)
+#define trace_dma_fence_signaled(a)
+#define trace_dma_fence_wait_end(a)
+#define trace_dma_fence_wait_start(a)
+
+#endif
diff --git a/sys/dev/pci/drm/include/uapi/drm/amdgpu_drm.h b/sys/dev/pci/drm/include/uapi/drm/amdgpu_drm.h
index 1ceec56de01..d28b4ce744d 100644
--- a/sys/dev/pci/drm/include/uapi/drm/amdgpu_drm.h
+++ b/sys/dev/pci/drm/include/uapi/drm/amdgpu_drm.h
@@ -125,9 +125,14 @@ extern "C" {
/* Flag that BO sharing will be explicitly synchronized */
#define AMDGPU_GEM_CREATE_EXPLICIT_SYNC (1 << 7)
/* Flag that indicates allocating MQD gart on GFX9, where the mtype
- * for the second page onward should be set to NC.
+ * for the second page onward should be set to NC. It should never
+ * be used by user space applications.
*/
-#define AMDGPU_GEM_CREATE_MQD_GFX9 (1 << 8)
+#define AMDGPU_GEM_CREATE_CP_MQD_GFX9 (1 << 8)
+/* Flag that BO may contain sensitive data that must be wiped before
+ * releasing the memory
+ */
+#define AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE (1 << 9)
struct drm_amdgpu_gem_create_in {
/** the requested memory size */
@@ -210,13 +215,19 @@ union drm_amdgpu_bo_list {
#define AMDGPU_CTX_QUERY2_FLAGS_VRAMLOST (1<<1)
/* indicate some job from this context once cause gpu hang */
#define AMDGPU_CTX_QUERY2_FLAGS_GUILTY (1<<2)
+/* indicate some errors are detected by RAS */
+#define AMDGPU_CTX_QUERY2_FLAGS_RAS_CE (1<<3)
+#define AMDGPU_CTX_QUERY2_FLAGS_RAS_UE (1<<4)
/* Context priority level */
#define AMDGPU_CTX_PRIORITY_UNSET -2048
#define AMDGPU_CTX_PRIORITY_VERY_LOW -1023
#define AMDGPU_CTX_PRIORITY_LOW -512
#define AMDGPU_CTX_PRIORITY_NORMAL 0
-/* Selecting a priority above NORMAL requires CAP_SYS_NICE or DRM_MASTER */
+/*
+ * When used in struct drm_amdgpu_ctx_in, a priority above NORMAL requires
+ * CAP_SYS_NICE or DRM_MASTER
+*/
#define AMDGPU_CTX_PRIORITY_HIGH 512
#define AMDGPU_CTX_PRIORITY_VERY_HIGH 1023
@@ -226,6 +237,7 @@ struct drm_amdgpu_ctx_in {
/** For future use, no flags defined so far */
__u32 flags;
__u32 ctx_id;
+ /** AMDGPU_CTX_PRIORITY_* */
__s32 priority;
};
@@ -272,13 +284,15 @@ union drm_amdgpu_vm {
/* sched ioctl */
#define AMDGPU_SCHED_OP_PROCESS_PRIORITY_OVERRIDE 1
+#define AMDGPU_SCHED_OP_CONTEXT_PRIORITY_OVERRIDE 2
struct drm_amdgpu_sched_in {
/* AMDGPU_SCHED_OP_* */
__u32 op;
__u32 fd;
+ /** AMDGPU_CTX_PRIORITY_* */
__s32 priority;
- __u32 flags;
+ __u32 ctx_id;
};
union drm_amdgpu_sched {
@@ -326,6 +340,16 @@ struct drm_amdgpu_gem_userptr {
/* GFX9 and later: */
#define AMDGPU_TILING_SWIZZLE_MODE_SHIFT 0
#define AMDGPU_TILING_SWIZZLE_MODE_MASK 0x1f
+#define AMDGPU_TILING_DCC_OFFSET_256B_SHIFT 5
+#define AMDGPU_TILING_DCC_OFFSET_256B_MASK 0xFFFFFF
+#define AMDGPU_TILING_DCC_PITCH_MAX_SHIFT 29
+#define AMDGPU_TILING_DCC_PITCH_MAX_MASK 0x3FFF
+#define AMDGPU_TILING_DCC_INDEPENDENT_64B_SHIFT 43
+#define AMDGPU_TILING_DCC_INDEPENDENT_64B_MASK 0x1
+#define AMDGPU_TILING_DCC_INDEPENDENT_128B_SHIFT 44
+#define AMDGPU_TILING_DCC_INDEPENDENT_128B_MASK 0x1
+#define AMDGPU_TILING_SCANOUT_SHIFT 63
+#define AMDGPU_TILING_SCANOUT_MASK 0x1
/* Set/Get helpers for tiling flags. */
#define AMDGPU_TILING_SET(field, value) \
@@ -481,6 +505,8 @@ struct drm_amdgpu_gem_op {
#define AMDGPU_VM_MTYPE_CC (3 << 5)
/* Use UC MTYPE instead of default MTYPE */
#define AMDGPU_VM_MTYPE_UC (4 << 5)
+/* Use RW MTYPE instead of default MTYPE */
+#define AMDGPU_VM_MTYPE_RW (5 << 5)
struct drm_amdgpu_gem_va {
/** GEM object handle */
@@ -517,6 +543,9 @@ struct drm_amdgpu_gem_va {
#define AMDGPU_CHUNK_ID_SYNCOBJ_IN 0x04
#define AMDGPU_CHUNK_ID_SYNCOBJ_OUT 0x05
#define AMDGPU_CHUNK_ID_BO_HANDLES 0x06
+#define AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES 0x07
+#define AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_WAIT 0x08
+#define AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_SIGNAL 0x09
struct drm_amdgpu_cs_chunk {
__u32 chunk_id;
@@ -559,6 +588,11 @@ union drm_amdgpu_cs {
* caches (L2/vL1/sL1/I$). */
#define AMDGPU_IB_FLAG_TC_WB_NOT_INVALIDATE (1 << 3)
+/* Set GDS_COMPUTE_MAX_WAVE_ID = DEFAULT before PACKET3_INDIRECT_BUFFER.
+ * This will reset wave ID counters for the IB.
+ */
+#define AMDGPU_IB_FLAG_RESET_GDS_MAX_WAVE_ID (1 << 4)
+
struct drm_amdgpu_cs_chunk_ib {
__u32 _pad;
/** AMDGPU_IB_FLAG_* */
@@ -592,6 +626,12 @@ struct drm_amdgpu_cs_chunk_sem {
__u32 handle;
};
+struct drm_amdgpu_cs_chunk_syncobj {
+ __u32 handle;
+ __u32 flags;
+ __u64 point;
+};
+
#define AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ 0
#define AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ_FD 1
#define AMDGPU_FENCE_TO_HANDLE_GET_SYNC_FILE_FD 2
@@ -665,6 +705,12 @@ struct drm_amdgpu_cs_chunk_data {
#define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_GPM_MEM 0x10
/* Subquery id: Query GFX RLC SRLS firmware version */
#define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_SRM_MEM 0x11
+ /* Subquery id: Query DMCU firmware version */
+ #define AMDGPU_INFO_FW_DMCU 0x12
+ #define AMDGPU_INFO_FW_TA 0x13
+ /* Subquery id: Query DMCUB firmware version */
+ #define AMDGPU_INFO_FW_DMCUB 0x14
+
/* number of bytes moved for TTM migration */
#define AMDGPU_INFO_NUM_BYTES_MOVED 0x0f
/* the used VRAM size */
@@ -718,6 +764,37 @@ struct drm_amdgpu_cs_chunk_data {
/* Number of VRAM page faults on CPU access. */
#define AMDGPU_INFO_NUM_VRAM_CPU_PAGE_FAULTS 0x1E
#define AMDGPU_INFO_VRAM_LOST_COUNTER 0x1F
+/* query ras mask of enabled features*/
+#define AMDGPU_INFO_RAS_ENABLED_FEATURES 0x20
+
+/* RAS MASK: UMC (VRAM) */
+#define AMDGPU_INFO_RAS_ENABLED_UMC (1 << 0)
+/* RAS MASK: SDMA */
+#define AMDGPU_INFO_RAS_ENABLED_SDMA (1 << 1)
+/* RAS MASK: GFX */
+#define AMDGPU_INFO_RAS_ENABLED_GFX (1 << 2)
+/* RAS MASK: MMHUB */
+#define AMDGPU_INFO_RAS_ENABLED_MMHUB (1 << 3)
+/* RAS MASK: ATHUB */
+#define AMDGPU_INFO_RAS_ENABLED_ATHUB (1 << 4)
+/* RAS MASK: PCIE */
+#define AMDGPU_INFO_RAS_ENABLED_PCIE (1 << 5)
+/* RAS MASK: HDP */
+#define AMDGPU_INFO_RAS_ENABLED_HDP (1 << 6)
+/* RAS MASK: XGMI */
+#define AMDGPU_INFO_RAS_ENABLED_XGMI (1 << 7)
+/* RAS MASK: DF */
+#define AMDGPU_INFO_RAS_ENABLED_DF (1 << 8)
+/* RAS MASK: SMN */
+#define AMDGPU_INFO_RAS_ENABLED_SMN (1 << 9)
+/* RAS MASK: SEM */
+#define AMDGPU_INFO_RAS_ENABLED_SEM (1 << 10)
+/* RAS MASK: MP0 */
+#define AMDGPU_INFO_RAS_ENABLED_MP0 (1 << 11)
+/* RAS MASK: MP1 */
+#define AMDGPU_INFO_RAS_ENABLED_MP1 (1 << 12)
+/* RAS MASK: FUSE */
+#define AMDGPU_INFO_RAS_ENABLED_FUSE (1 << 13)
#define AMDGPU_INFO_MMR_SE_INDEX_SHIFT 0
#define AMDGPU_INFO_MMR_SE_INDEX_MASK 0xff
@@ -854,6 +931,7 @@ struct drm_amdgpu_info_firmware {
#define AMDGPU_VRAM_TYPE_HBM 6
#define AMDGPU_VRAM_TYPE_DDR3 7
#define AMDGPU_VRAM_TYPE_DDR4 8
+#define AMDGPU_VRAM_TYPE_GDDR6 9
struct drm_amdgpu_info_device {
/** PCI Device ID */
@@ -933,6 +1011,10 @@ struct drm_amdgpu_info_device {
__u64 high_va_offset;
/** The maximum high virtual address */
__u64 high_va_max;
+ /* gfx10 pa_sc_tile_steering_override */
+ __u32 pa_sc_tile_steering_override;
+ /* disabled TCCs */
+ __u64 tcc_disabled_mask;
};
struct drm_amdgpu_info_hw_ip {
@@ -986,6 +1068,7 @@ struct drm_amdgpu_info_vce_clock_table {
#define AMDGPU_FAMILY_CZ 135 /* Carrizo, Stoney */
#define AMDGPU_FAMILY_AI 141 /* Vega10 */
#define AMDGPU_FAMILY_RV 142 /* Raven */
+#define AMDGPU_FAMILY_NV 143 /* Navi10 */
#if defined(__cplusplus)
}
diff --git a/sys/dev/pci/drm/include/uapi/drm/drm.h b/sys/dev/pci/drm/include/uapi/drm/drm.h
index 97b43504e88..58bb4254250 100644
--- a/sys/dev/pci/drm/include/uapi/drm/drm.h
+++ b/sys/dev/pci/drm/include/uapi/drm/drm.h
@@ -653,6 +653,7 @@ struct drm_gem_open {
#define DRM_CAP_PAGE_FLIP_TARGET 0x11
#define DRM_CAP_CRTC_IN_VBLANK_EVENT 0x12
#define DRM_CAP_SYNCOBJ 0x13
+#define DRM_CAP_SYNCOBJ_TIMELINE 0x14
/** DRM_IOCTL_GET_CAP ioctl argument type */
struct drm_get_cap {
@@ -739,8 +740,18 @@ struct drm_syncobj_handle {
__u32 pad;
};
+struct drm_syncobj_transfer {
+ __u32 src_handle;
+ __u32 dst_handle;
+ __u64 src_point;
+ __u64 dst_point;
+ __u32 flags;
+ __u32 pad;
+};
+
#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0)
#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1)
+#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE (1 << 2) /* wait for time point to become available */
struct drm_syncobj_wait {
__u64 handles;
/* absolute timeout */
@@ -751,12 +762,34 @@ struct drm_syncobj_wait {
__u32 pad;
};
+struct drm_syncobj_timeline_wait {
+ __u64 handles;
+ /* wait on specific timeline point for every handles*/
+ __u64 points;
+ /* absolute timeout */
+ __s64 timeout_nsec;
+ __u32 count_handles;
+ __u32 flags;
+ __u32 first_signaled; /* only valid when not waiting all */
+ __u32 pad;
+};
+
+
struct drm_syncobj_array {
__u64 handles;
__u32 count_handles;
__u32 pad;
};
+#define DRM_SYNCOBJ_QUERY_FLAGS_LAST_SUBMITTED (1 << 0) /* last available point on timeline syncobj */
+struct drm_syncobj_timeline_array {
+ __u64 handles;
+ __u64 points;
+ __u32 count_handles;
+ __u32 flags;
+};
+
+
/* Query current scanout sequence number */
struct drm_crtc_get_sequence {
__u32 crtc_id; /* requested crtc_id */
@@ -917,6 +950,13 @@ extern "C" {
#define DRM_IOCTL_MODE_GET_LEASE DRM_IOWR(0xC8, struct drm_mode_get_lease)
#define DRM_IOCTL_MODE_REVOKE_LEASE DRM_IOWR(0xC9, struct drm_mode_revoke_lease)
+#define DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT DRM_IOWR(0xCA, struct drm_syncobj_timeline_wait)
+#define DRM_IOCTL_SYNCOBJ_QUERY DRM_IOWR(0xCB, struct drm_syncobj_timeline_array)
+#define DRM_IOCTL_SYNCOBJ_TRANSFER DRM_IOWR(0xCC, struct drm_syncobj_transfer)
+#define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL DRM_IOWR(0xCD, struct drm_syncobj_timeline_array)
+
+#define DRM_IOCTL_MODE_GETFB2 DRM_IOWR(0xCE, struct drm_mode_fb_cmd2)
+
/**
* Device specific ioctls should only be in their respective headers
* The device specific ioctl range is from 0x40 to 0x9f.
diff --git a/sys/dev/pci/drm/include/uapi/drm/drm_fourcc.h b/sys/dev/pci/drm/include/uapi/drm/drm_fourcc.h
index 721ab7e54d9..8bc0b31597d 100644
--- a/sys/dev/pci/drm/include/uapi/drm/drm_fourcc.h
+++ b/sys/dev/pci/drm/include/uapi/drm/drm_fourcc.h
@@ -30,10 +30,49 @@
extern "C" {
#endif
+/**
+ * DOC: overview
+ *
+ * In the DRM subsystem, framebuffer pixel formats are described using the
+ * fourcc codes defined in `include/uapi/drm/drm_fourcc.h`. In addition to the
+ * fourcc code, a Format Modifier may optionally be provided, in order to
+ * further describe the buffer's format - for example tiling or compression.
+ *
+ * Format Modifiers
+ * ----------------
+ *
+ * Format modifiers are used in conjunction with a fourcc code, forming a
+ * unique fourcc:modifier pair. This format:modifier pair must fully define the
+ * format and data layout of the buffer, and should be the only way to describe
+ * that particular buffer.
+ *
+ * Having multiple fourcc:modifier pairs which describe the same layout should
+ * be avoided, as such aliases run the risk of different drivers exposing
+ * different names for the same data format, forcing userspace to understand
+ * that they are aliases.
+ *
+ * Format modifiers may change any property of the buffer, including the number
+ * of planes and/or the required allocation size. Format modifiers are
+ * vendor-namespaced, and as such the relationship between a fourcc code and a
+ * modifier is specific to the modifer being used. For example, some modifiers
+ * may preserve meaning - such as number of planes - from the fourcc code,
+ * whereas others may not.
+ *
+ * Vendors should document their modifier usage in as much detail as
+ * possible, to ensure maximum compatibility across devices, drivers and
+ * applications.
+ *
+ * The authoritative list of format modifier codes is found in
+ * `include/uapi/drm/drm_fourcc.h`
+ */
+
#define fourcc_code(a, b, c, d) ((__u32)(a) | ((__u32)(b) << 8) | \
((__u32)(c) << 16) | ((__u32)(d) << 24))
-#define DRM_FORMAT_BIG_ENDIAN (1<<31) /* format is big endian instead of little endian */
+#define DRM_FORMAT_BIG_ENDIAN (1U<<31) /* format is big endian instead of little endian */
+
+/* Reserve 0 for the invalid format specifier */
+#define DRM_FORMAT_INVALID 0
/* color index */
#define DRM_FORMAT_C8 fourcc_code('C', '8', ' ', ' ') /* [7:0] C */
@@ -105,6 +144,17 @@ extern "C" {
#define DRM_FORMAT_RGBA1010102 fourcc_code('R', 'A', '3', '0') /* [31:0] R:G:B:A 10:10:10:2 little endian */
#define DRM_FORMAT_BGRA1010102 fourcc_code('B', 'A', '3', '0') /* [31:0] B:G:R:A 10:10:10:2 little endian */
+/*
+ * Floating point 64bpp RGB
+ * IEEE 754-2008 binary16 half-precision float
+ * [15:0] sign:exponent:mantissa 1:5:10
+ */
+#define DRM_FORMAT_XRGB16161616F fourcc_code('X', 'R', '4', 'H') /* [63:0] x:R:G:B 16:16:16:16 little endian */
+#define DRM_FORMAT_XBGR16161616F fourcc_code('X', 'B', '4', 'H') /* [63:0] x:B:G:R 16:16:16:16 little endian */
+
+#define DRM_FORMAT_ARGB16161616F fourcc_code('A', 'R', '4', 'H') /* [63:0] A:R:G:B 16:16:16:16 little endian */
+#define DRM_FORMAT_ABGR16161616F fourcc_code('A', 'B', '4', 'H') /* [63:0] A:B:G:R 16:16:16:16 little endian */
+
/* packed YCbCr */
#define DRM_FORMAT_YUYV fourcc_code('Y', 'U', 'Y', 'V') /* [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian */
#define DRM_FORMAT_YVYU fourcc_code('Y', 'V', 'Y', 'U') /* [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian */
@@ -112,6 +162,52 @@ extern "C" {
#define DRM_FORMAT_VYUY fourcc_code('V', 'Y', 'U', 'Y') /* [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian */
#define DRM_FORMAT_AYUV fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */
+#define DRM_FORMAT_XYUV8888 fourcc_code('X', 'Y', 'U', 'V') /* [31:0] X:Y:Cb:Cr 8:8:8:8 little endian */
+#define DRM_FORMAT_VUY888 fourcc_code('V', 'U', '2', '4') /* [23:0] Cr:Cb:Y 8:8:8 little endian */
+#define DRM_FORMAT_VUY101010 fourcc_code('V', 'U', '3', '0') /* Y followed by U then V, 10:10:10. Non-linear modifier only */
+
+/*
+ * packed Y2xx indicate for each component, xx valid data occupy msb
+ * 16-xx padding occupy lsb
+ */
+#define DRM_FORMAT_Y210 fourcc_code('Y', '2', '1', '0') /* [63:0] Cr0:0:Y1:0:Cb0:0:Y0:0 10:6:10:6:10:6:10:6 little endian per 2 Y pixels */
+#define DRM_FORMAT_Y212 fourcc_code('Y', '2', '1', '2') /* [63:0] Cr0:0:Y1:0:Cb0:0:Y0:0 12:4:12:4:12:4:12:4 little endian per 2 Y pixels */
+#define DRM_FORMAT_Y216 fourcc_code('Y', '2', '1', '6') /* [63:0] Cr0:Y1:Cb0:Y0 16:16:16:16 little endian per 2 Y pixels */
+
+/*
+ * packed Y4xx indicate for each component, xx valid data occupy msb
+ * 16-xx padding occupy lsb except Y410
+ */
+#define DRM_FORMAT_Y410 fourcc_code('Y', '4', '1', '0') /* [31:0] A:Cr:Y:Cb 2:10:10:10 little endian */
+#define DRM_FORMAT_Y412 fourcc_code('Y', '4', '1', '2') /* [63:0] A:0:Cr:0:Y:0:Cb:0 12:4:12:4:12:4:12:4 little endian */
+#define DRM_FORMAT_Y416 fourcc_code('Y', '4', '1', '6') /* [63:0] A:Cr:Y:Cb 16:16:16:16 little endian */
+
+#define DRM_FORMAT_XVYU2101010 fourcc_code('X', 'V', '3', '0') /* [31:0] X:Cr:Y:Cb 2:10:10:10 little endian */
+#define DRM_FORMAT_XVYU12_16161616 fourcc_code('X', 'V', '3', '6') /* [63:0] X:0:Cr:0:Y:0:Cb:0 12:4:12:4:12:4:12:4 little endian */
+#define DRM_FORMAT_XVYU16161616 fourcc_code('X', 'V', '4', '8') /* [63:0] X:Cr:Y:Cb 16:16:16:16 little endian */
+
+/*
+ * packed YCbCr420 2x2 tiled formats
+ * first 64 bits will contain Y,Cb,Cr components for a 2x2 tile
+ */
+/* [63:0] A3:A2:Y3:0:Cr0:0:Y2:0:A1:A0:Y1:0:Cb0:0:Y0:0 1:1:8:2:8:2:8:2:1:1:8:2:8:2:8:2 little endian */
+#define DRM_FORMAT_Y0L0 fourcc_code('Y', '0', 'L', '0')
+/* [63:0] X3:X2:Y3:0:Cr0:0:Y2:0:X1:X0:Y1:0:Cb0:0:Y0:0 1:1:8:2:8:2:8:2:1:1:8:2:8:2:8:2 little endian */
+#define DRM_FORMAT_X0L0 fourcc_code('X', '0', 'L', '0')
+
+/* [63:0] A3:A2:Y3:Cr0:Y2:A1:A0:Y1:Cb0:Y0 1:1:10:10:10:1:1:10:10:10 little endian */
+#define DRM_FORMAT_Y0L2 fourcc_code('Y', '0', 'L', '2')
+/* [63:0] X3:X2:Y3:Cr0:Y2:X1:X0:Y1:Cb0:Y0 1:1:10:10:10:1:1:10:10:10 little endian */
+#define DRM_FORMAT_X0L2 fourcc_code('X', '0', 'L', '2')
+
+/*
+ * 1-plane YUV 4:2:0
+ * In these formats, the component ordering is specified (Y, followed by U
+ * then V), but the exact Linear layout is undefined.
+ * These formats can only be used with a non-Linear modifier.
+ */
+#define DRM_FORMAT_YUV420_8BIT fourcc_code('Y', 'U', '0', '8')
+#define DRM_FORMAT_YUV420_10BIT fourcc_code('Y', 'U', '1', '0')
/*
* 2 plane RGB + A
@@ -142,6 +238,34 @@ extern "C" {
#define DRM_FORMAT_NV42 fourcc_code('N', 'V', '4', '2') /* non-subsampled Cb:Cr plane */
/*
+ * 2 plane YCbCr MSB aligned
+ * index 0 = Y plane, [15:0] Y:x [10:6] little endian
+ * index 1 = Cr:Cb plane, [31:0] Cr:x:Cb:x [10:6:10:6] little endian
+ */
+#define DRM_FORMAT_P210 fourcc_code('P', '2', '1', '0') /* 2x1 subsampled Cr:Cb plane, 10 bit per channel */
+
+/*
+ * 2 plane YCbCr MSB aligned
+ * index 0 = Y plane, [15:0] Y:x [10:6] little endian
+ * index 1 = Cr:Cb plane, [31:0] Cr:x:Cb:x [10:6:10:6] little endian
+ */
+#define DRM_FORMAT_P010 fourcc_code('P', '0', '1', '0') /* 2x2 subsampled Cr:Cb plane 10 bits per channel */
+
+/*
+ * 2 plane YCbCr MSB aligned
+ * index 0 = Y plane, [15:0] Y:x [12:4] little endian
+ * index 1 = Cr:Cb plane, [31:0] Cr:x:Cb:x [12:4:12:4] little endian
+ */
+#define DRM_FORMAT_P012 fourcc_code('P', '0', '1', '2') /* 2x2 subsampled Cr:Cb plane 12 bits per channel */
+
+/*
+ * 2 plane YCbCr MSB aligned
+ * index 0 = Y plane, [15:0] Y little endian
+ * index 1 = Cr:Cb plane, [31:0] Cr:Cb [16:16] little endian
+ */
+#define DRM_FORMAT_P016 fourcc_code('P', '0', '1', '6') /* 2x2 subsampled Cr:Cb plane 16 bits per channel */
+
+/*
* 3 plane YCbCr
* index 0: Y plane, [7:0] Y
* index 1: Cb plane, [7:0] Cb
@@ -184,6 +308,8 @@ extern "C" {
#define DRM_FORMAT_MOD_VENDOR_VIVANTE 0x06
#define DRM_FORMAT_MOD_VENDOR_BROADCOM 0x07
#define DRM_FORMAT_MOD_VENDOR_ARM 0x08
+#define DRM_FORMAT_MOD_VENDOR_ALLWINNER 0x09
+
/* add more to the end as needed */
#define DRM_FORMAT_RESERVED ((1ULL << 56) - 1)
@@ -285,6 +411,30 @@ extern "C" {
#define I915_FORMAT_MOD_Yf_TILED_CCS fourcc_mod_code(INTEL, 5)
/*
+ * Intel color control surfaces (CCS) for Gen-12 render compression.
+ *
+ * The main surface is Y-tiled and at plane index 0, the CCS is linear and
+ * at index 1. A 64B CCS cache line corresponds to an area of 4x1 tiles in
+ * main surface. In other words, 4 bits in CCS map to a main surface cache
+ * line pair. The main surface pitch is required to be a multiple of four
+ * Y-tile widths.
+ */
+#define I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS fourcc_mod_code(INTEL, 6)
+
+/*
+ * Intel color control surfaces (CCS) for Gen-12 media compression
+ *
+ * The main surface is Y-tiled and at plane index 0, the CCS is linear and
+ * at index 1. A 64B CCS cache line corresponds to an area of 4x1 tiles in
+ * main surface. In other words, 4 bits in CCS map to a main surface cache
+ * line pair. The main surface pitch is required to be a multiple of four
+ * Y-tile widths. For semi-planar formats like NV12, CCS planes follow the
+ * Y and UV planes i.e., planes 0 and 1 are used for Y and UV surfaces,
+ * planes 2 and 3 for the respective CCS.
+ */
+#define I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS fourcc_mod_code(INTEL, 7)
+
+/*
* Tiled, NV12MT, grouped in 64 (pixels) x 32 (lines) -sized macroblocks
*
* Macroblocks are laid in a Z-shape, and each pixel data is following the
@@ -300,6 +450,15 @@ extern "C" {
#define DRM_FORMAT_MOD_SAMSUNG_64_32_TILE fourcc_mod_code(SAMSUNG, 1)
/*
+ * Tiled, 16 (pixels) x 16 (lines) - sized macroblocks
+ *
+ * This is a simple tiled layout using tiles of 16x16 pixels in a row-major
+ * layout. For YCbCr formats Cb/Cr components are taken in such a way that
+ * they correspond to their 16x16 luma block.
+ */
+#define DRM_FORMAT_MOD_SAMSUNG_16_16_TILE fourcc_mod_code(SAMSUNG, 2)
+
+/*
* Qualcomm Compressed Format
*
* Refers to a compressed variant of the base format that is compressed.
@@ -509,8 +668,25 @@ extern "C" {
* AFBC has several features which may be supported and/or used, which are
* represented using bits in the modifier. Not all combinations are valid,
* and different devices or use-cases may support different combinations.
+ *
+ * Further information on the use of AFBC modifiers can be found in
+ * Documentation/gpu/afbc.rst
*/
-#define DRM_FORMAT_MOD_ARM_AFBC(__afbc_mode) fourcc_mod_code(ARM, __afbc_mode)
+
+/*
+ * The top 4 bits (out of the 56 bits alloted for specifying vendor specific
+ * modifiers) denote the category for modifiers. Currently we have only two
+ * categories of modifiers ie AFBC and MISC. We can have a maximum of sixteen
+ * different categories.
+ */
+#define DRM_FORMAT_MOD_ARM_CODE(__type, __val) \
+ fourcc_mod_code(ARM, ((__u64)(__type) << 52) | ((__val) & 0x000fffffffffffffULL))
+
+#define DRM_FORMAT_MOD_ARM_TYPE_AFBC 0x00
+#define DRM_FORMAT_MOD_ARM_TYPE_MISC 0x01
+
+#define DRM_FORMAT_MOD_ARM_AFBC(__afbc_mode) \
+ DRM_FORMAT_MOD_ARM_CODE(DRM_FORMAT_MOD_ARM_TYPE_AFBC, __afbc_mode)
/*
* AFBC superblock size
@@ -518,10 +694,18 @@ extern "C" {
* Indicates the superblock size(s) used for the AFBC buffer. The buffer
* size (in pixels) must be aligned to a multiple of the superblock size.
* Four lowest significant bits(LSBs) are reserved for block size.
+ *
+ * Where one superblock size is specified, it applies to all planes of the
+ * buffer (e.g. 16x16, 32x8). When multiple superblock sizes are specified,
+ * the first applies to the Luma plane and the second applies to the Chroma
+ * plane(s). e.g. (32x8_64x4 means 32x8 Luma, with 64x4 Chroma).
+ * Multiple superblock sizes are only valid for multi-plane YCbCr formats.
*/
#define AFBC_FORMAT_MOD_BLOCK_SIZE_MASK 0xf
#define AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 (1ULL)
#define AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 (2ULL)
+#define AFBC_FORMAT_MOD_BLOCK_SIZE_64x4 (3ULL)
+#define AFBC_FORMAT_MOD_BLOCK_SIZE_32x8_64x4 (4ULL)
/*
* AFBC lossless colorspace transform
@@ -581,6 +765,45 @@ extern "C" {
*/
#define AFBC_FORMAT_MOD_SC (1ULL << 9)
+/*
+ * AFBC double-buffer
+ *
+ * Indicates that the buffer is allocated in a layout safe for front-buffer
+ * rendering.
+ */
+#define AFBC_FORMAT_MOD_DB (1ULL << 10)
+
+/*
+ * AFBC buffer content hints
+ *
+ * Indicates that the buffer includes per-superblock content hints.
+ */
+#define AFBC_FORMAT_MOD_BCH (1ULL << 11)
+
+/*
+ * Arm 16x16 Block U-Interleaved modifier
+ *
+ * This is used by Arm Mali Utgard and Midgard GPUs. It divides the image
+ * into 16x16 pixel blocks. Blocks are stored linearly in order, but pixels
+ * in the block are reordered.
+ */
+#define DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED \
+ DRM_FORMAT_MOD_ARM_CODE(DRM_FORMAT_MOD_ARM_TYPE_MISC, 1ULL)
+
+/*
+ * Allwinner tiled modifier
+ *
+ * This tiling mode is implemented by the VPU found on all Allwinner platforms,
+ * codenamed sunxi. It is associated with a YUV format that uses either 2 or 3
+ * planes.
+ *
+ * With this tiling, the luminance samples are disposed in tiles representing
+ * 32x32 pixels and the chrominance samples in tiles representing 32x64 pixels.
+ * The pixel order in each tile is linear and the tiles are disposed linearly,
+ * both in row-major order.
+ */
+#define DRM_FORMAT_MOD_ALLWINNER_TILED fourcc_mod_code(ALLWINNER, 1)
+
#if defined(__cplusplus)
}
#endif
diff --git a/sys/dev/pci/drm/include/uapi/drm/drm_mode.h b/sys/dev/pci/drm/include/uapi/drm/drm_mode.h
index 8d67243952f..735c8cfdaaa 100644
--- a/sys/dev/pci/drm/include/uapi/drm/drm_mode.h
+++ b/sys/dev/pci/drm/include/uapi/drm/drm_mode.h
@@ -33,7 +33,15 @@
extern "C" {
#endif
-#define DRM_DISPLAY_INFO_LEN 32
+/**
+ * DOC: overview
+ *
+ * DRM exposes many UAPI and structure definition to have a consistent
+ * and standardized interface with user.
+ * Userspace can refer to these structure definitions and UAPI formats
+ * to communicate to driver
+ */
+
#define DRM_CONNECTOR_NAME_LEN 32
#define DRM_DISPLAY_MODE_LEN 32
#define DRM_PROP_NAME_LEN 32
@@ -186,8 +194,9 @@ extern "C" {
/*
* DRM_MODE_REFLECT_<axis>
*
- * Signals that the contents of a drm plane is reflected in the <axis> axis,
+ * Signals that the contents of a drm plane is reflected along the <axis> axis,
* in the same way as mirroring.
+ * See kerneldoc chapter "Plane Composition Properties" for more details.
*
* This define is provided as a convenience, looking up the property id
* using the name->prop id lookup is the preferred method.
@@ -352,6 +361,7 @@ enum drm_mode_subconnector {
#define DRM_MODE_CONNECTOR_DSI 16
#define DRM_MODE_CONNECTOR_DPI 17
#define DRM_MODE_CONNECTOR_WRITEBACK 18
+#define DRM_MODE_CONNECTOR_SPI 19
struct drm_mode_get_connector {
@@ -621,7 +631,8 @@ struct drm_color_ctm {
struct drm_color_lut {
/*
- * Data is U0.16 fixed point format.
+ * Values are mapped linearly to 0.0 - 1.0 range, with 0x0 == 0.0 and
+ * 0xffff == 1.0.
*/
__u16 red;
__u16 green;
@@ -629,6 +640,92 @@ struct drm_color_lut {
__u16 reserved;
};
+/**
+ * struct hdr_metadata_infoframe - HDR Metadata Infoframe Data.
+ *
+ * HDR Metadata Infoframe as per CTA 861.G spec. This is expected
+ * to match exactly with the spec.
+ *
+ * Userspace is expected to pass the metadata information as per
+ * the format described in this structure.
+ */
+struct hdr_metadata_infoframe {
+ /**
+ * @eotf: Electro-Optical Transfer Function (EOTF)
+ * used in the stream.
+ */
+ __u8 eotf;
+ /**
+ * @metadata_type: Static_Metadata_Descriptor_ID.
+ */
+ __u8 metadata_type;
+ /**
+ * @display_primaries: Color Primaries of the Data.
+ * These are coded as unsigned 16-bit values in units of
+ * 0.00002, where 0x0000 represents zero and 0xC350
+ * represents 1.0000.
+ * @display_primaries.x: X cordinate of color primary.
+ * @display_primaries.y: Y cordinate of color primary.
+ */
+ struct {
+ __u16 x, y;
+ } display_primaries[3];
+ /**
+ * @white_point: White Point of Colorspace Data.
+ * These are coded as unsigned 16-bit values in units of
+ * 0.00002, where 0x0000 represents zero and 0xC350
+ * represents 1.0000.
+ * @white_point.x: X cordinate of whitepoint of color primary.
+ * @white_point.y: Y cordinate of whitepoint of color primary.
+ */
+ struct {
+ __u16 x, y;
+ } white_point;
+ /**
+ * @max_display_mastering_luminance: Max Mastering Display Luminance.
+ * This value is coded as an unsigned 16-bit value in units of 1 cd/m2,
+ * where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2.
+ */
+ __u16 max_display_mastering_luminance;
+ /**
+ * @min_display_mastering_luminance: Min Mastering Display Luminance.
+ * This value is coded as an unsigned 16-bit value in units of
+ * 0.0001 cd/m2, where 0x0001 represents 0.0001 cd/m2 and 0xFFFF
+ * represents 6.5535 cd/m2.
+ */
+ __u16 min_display_mastering_luminance;
+ /**
+ * @max_cll: Max Content Light Level.
+ * This value is coded as an unsigned 16-bit value in units of 1 cd/m2,
+ * where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2.
+ */
+ __u16 max_cll;
+ /**
+ * @max_fall: Max Frame Average Light Level.
+ * This value is coded as an unsigned 16-bit value in units of 1 cd/m2,
+ * where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2.
+ */
+ __u16 max_fall;
+};
+
+/**
+ * struct hdr_output_metadata - HDR output metadata
+ *
+ * Metadata Information to be passed from userspace
+ */
+struct hdr_output_metadata {
+ /**
+ * @metadata_type: Static_Metadata_Descriptor_ID.
+ */
+ __u32 metadata_type;
+ /**
+ * @hdmi_metadata_type1: HDR Metadata Infoframe.
+ */
+ union {
+ struct hdr_metadata_infoframe hdmi_metadata_type1;
+ };
+};
+
#define DRM_MODE_PAGE_FLIP_EVENT 0x01
#define DRM_MODE_PAGE_FLIP_ASYNC 0x02
#define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4
@@ -802,6 +899,10 @@ struct drm_format_modifier {
};
/**
+ * struct drm_mode_create_blob - Create New block property
+ * @data: Pointer to data to copy.
+ * @length: Length of data to copy.
+ * @blob_id: new property ID.
* Create a new 'blob' data property, copying length bytes from data pointer,
* and returning new blob ID.
*/
@@ -815,6 +916,8 @@ struct drm_mode_create_blob {
};
/**
+ * struct drm_mode_destroy_blob - Destroy user blob
+ * @blob_id: blob_id to destroy
* Destroy a user-created blob property.
*/
struct drm_mode_destroy_blob {
@@ -822,6 +925,12 @@ struct drm_mode_destroy_blob {
};
/**
+ * struct drm_mode_create_lease - Create lease
+ * @object_ids: Pointer to array of object ids.
+ * @object_count: Number of object ids.
+ * @flags: flags for new FD.
+ * @lessee_id: unique identifier for lessee.
+ * @fd: file descriptor to new drm_master file.
* Lease mode resources, creating another drm_master.
*/
struct drm_mode_create_lease {
@@ -839,6 +948,10 @@ struct drm_mode_create_lease {
};
/**
+ * struct drm_mode_list_lessees - List lessees
+ * @count_lessees: Number of lessees.
+ * @pad: pad.
+ * @lessees_ptr: Pointer to lessess.
* List lesses from a drm_master
*/
struct drm_mode_list_lessees {
@@ -859,6 +972,10 @@ struct drm_mode_list_lessees {
};
/**
+ * struct drm_mode_get_lease - Get Lease
+ * @count_objects: Number of leased objects.
+ * @pad: pad.
+ * @objects_ptr: Pointer to objects.
* Get leased objects
*/
struct drm_mode_get_lease {
@@ -879,6 +996,8 @@ struct drm_mode_get_lease {
};
/**
+ * struct drm_mode_revoke_lease - Revoke lease
+ * @lessee_id: Unique ID of lessee.
* Revoke lease
*/
struct drm_mode_revoke_lease {
@@ -887,6 +1006,25 @@ struct drm_mode_revoke_lease {
__u32 lessee_id;
};
+/**
+ * struct drm_mode_rect - Two dimensional rectangle.
+ * @x1: Horizontal starting coordinate (inclusive).
+ * @y1: Vertical starting coordinate (inclusive).
+ * @x2: Horizontal ending coordinate (exclusive).
+ * @y2: Vertical ending coordinate (exclusive).
+ *
+ * With drm subsystem using struct drm_rect to manage rectangular area this
+ * export it to user-space.
+ *
+ * Currently used by drm_mode_atomic blob property FB_DAMAGE_CLIPS.
+ */
+struct drm_mode_rect {
+ __s32 x1;
+ __s32 y1;
+ __s32 x2;
+ __s32 y2;
+};
+
#if defined(__cplusplus)
}
#endif
diff --git a/sys/dev/pci/drm/include/uapi/drm/i915_drm.h b/sys/dev/pci/drm/include/uapi/drm/i915_drm.h
index 4671c9150d4..2813e579b48 100644
--- a/sys/dev/pci/drm/include/uapi/drm/i915_drm.h
+++ b/sys/dev/pci/drm/include/uapi/drm/i915_drm.h
@@ -63,6 +63,28 @@ extern "C" {
#define I915_RESET_UEVENT "RESET"
/*
+ * i915_user_extension: Base class for defining a chain of extensions
+ *
+ * Many interfaces need to grow over time. In most cases we can simply
+ * extend the struct and have userspace pass in more data. Another option,
+ * as demonstrated by Vulkan's approach to providing extensions for forward
+ * and backward compatibility, is to use a list of optional structs to
+ * provide those extra details.
+ *
+ * The key advantage to using an extension chain is that it allows us to
+ * redefine the interface more easily than an ever growing struct of
+ * increasing complexity, and for large parts of that interface to be
+ * entirely optional. The downside is more pointer chasing; chasing across
+ * the __user boundary with pointers encapsulated inside u64.
+ */
+struct i915_user_extension {
+ __u64 next_extension;
+ __u32 name;
+ __u32 flags; /* All undefined bits must be zero. */
+ __u32 rsvd[4]; /* Reserved for future use; must be zero. */
+};
+
+/*
* MOCS indexes used for GPU surfaces, defining the cacheability of the
* surface data and the coherency for this data wrt. CPU vs. GPU accesses.
*/
@@ -99,9 +121,25 @@ enum drm_i915_gem_engine_class {
I915_ENGINE_CLASS_VIDEO = 2,
I915_ENGINE_CLASS_VIDEO_ENHANCE = 3,
+ /* should be kept compact */
+
I915_ENGINE_CLASS_INVALID = -1
};
+/*
+ * There may be more than one engine fulfilling any role within the system.
+ * Each engine of a class is given a unique instance number and therefore
+ * any engine can be specified by its class:instance tuplet. APIs that allow
+ * access to any engine in the system will use struct i915_engine_class_instance
+ * for this identification.
+ */
+struct i915_engine_class_instance {
+ __u16 engine_class; /* see enum drm_i915_gem_engine_class */
+ __u16 engine_instance;
+#define I915_ENGINE_CLASS_INVALID_NONE -1
+#define I915_ENGINE_CLASS_INVALID_VIRTUAL -2
+};
+
/**
* DOC: perf_events exposed by i915 through /sys/bus/event_sources/drivers/i915
*
@@ -319,6 +357,9 @@ typedef struct _drm_i915_sarea {
#define DRM_I915_PERF_ADD_CONFIG 0x37
#define DRM_I915_PERF_REMOVE_CONFIG 0x38
#define DRM_I915_QUERY 0x39
+#define DRM_I915_GEM_VM_CREATE 0x3a
+#define DRM_I915_GEM_VM_DESTROY 0x3b
+/* Must be kept compact -- no holes */
#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -354,6 +395,7 @@ typedef struct _drm_i915_sarea {
#define DRM_IOCTL_I915_GEM_PWRITE DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite)
#define DRM_IOCTL_I915_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap)
#define DRM_IOCTL_I915_GEM_MMAP_GTT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP_GTT, struct drm_i915_gem_mmap_gtt)
+#define DRM_IOCTL_I915_GEM_MMAP_OFFSET DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP_GTT, struct drm_i915_gem_mmap_offset)
#define DRM_IOCTL_I915_GEM_SET_DOMAIN DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain)
#define DRM_IOCTL_I915_GEM_SW_FINISH DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish)
#define DRM_IOCTL_I915_GEM_SET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling)
@@ -367,6 +409,7 @@ typedef struct _drm_i915_sarea {
#define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey)
#define DRM_IOCTL_I915_GEM_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_WAIT, struct drm_i915_gem_wait)
#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create)
+#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE_EXT DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create_ext)
#define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy)
#define DRM_IOCTL_I915_REG_READ DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_REG_READ, struct drm_i915_reg_read)
#define DRM_IOCTL_I915_GET_RESET_STATS DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GET_RESET_STATS, struct drm_i915_reset_stats)
@@ -377,6 +420,8 @@ typedef struct _drm_i915_sarea {
#define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config)
#define DRM_IOCTL_I915_PERF_REMOVE_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64)
#define DRM_IOCTL_I915_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query)
+#define DRM_IOCTL_I915_GEM_VM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_VM_CREATE, struct drm_i915_gem_vm_control)
+#define DRM_IOCTL_I915_GEM_VM_DESTROY DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_VM_DESTROY, struct drm_i915_gem_vm_control)
/* Allow drivers to submit batchbuffers directly to hardware, relying
* on the security mechanisms provided by hardware.
@@ -412,6 +457,14 @@ typedef struct drm_i915_irq_wait {
int irq_seq;
} drm_i915_irq_wait_t;
+/*
+ * Different modes of per-process Graphics Translation Table,
+ * see I915_PARAM_HAS_ALIASING_PPGTT
+ */
+#define I915_GEM_PPGTT_NONE 0
+#define I915_GEM_PPGTT_ALIASING 1
+#define I915_GEM_PPGTT_FULL 2
+
/* Ioctl to query kernel params:
*/
#define I915_PARAM_IRQ_ACTIVE 1
@@ -468,6 +521,8 @@ typedef struct drm_i915_irq_wait {
#define I915_SCHEDULER_CAP_ENABLED (1ul << 0)
#define I915_SCHEDULER_CAP_PRIORITY (1ul << 1)
#define I915_SCHEDULER_CAP_PREEMPTION (1ul << 2)
+#define I915_SCHEDULER_CAP_SEMAPHORES (1ul << 3)
+#define I915_SCHEDULER_CAP_ENGINE_BUSY_STATS (1ul << 4)
#define I915_PARAM_HUC_STATUS 42
@@ -529,6 +584,43 @@ typedef struct drm_i915_irq_wait {
*/
#define I915_PARAM_CS_TIMESTAMP_FREQUENCY 51
+/*
+ * Once upon a time we supposed that writes through the GGTT would be
+ * immediately in physical memory (once flushed out of the CPU path). However,
+ * on a few different processors and chipsets, this is not necessarily the case
+ * as the writes appear to be buffered internally. Thus a read of the backing
+ * storage (physical memory) via a different path (with different physical tags
+ * to the indirect write via the GGTT) will see stale values from before
+ * the GGTT write. Inside the kernel, we can for the most part keep track of
+ * the different read/write domains in use (e.g. set-domain), but the assumption
+ * of coherency is baked into the ABI, hence reporting its true state in this
+ * parameter.
+ *
+ * Reports true when writes via mmap_gtt are immediately visible following an
+ * lfence to flush the WCB.
+ *
+ * Reports false when writes via mmap_gtt are indeterminately delayed in an in
+ * internal buffer and are _not_ immediately visible to third parties accessing
+ * directly via mmap_cpu/mmap_wc. Use of mmap_gtt as part of an IPC
+ * communications channel when reporting false is strongly disadvised.
+ */
+#define I915_PARAM_MMAP_GTT_COHERENT 52
+
+/*
+ * Query whether DRM_I915_GEM_EXECBUFFER2 supports coordination of parallel
+ * execution through use of explicit fence support.
+ * See I915_EXEC_FENCE_OUT and I915_EXEC_FENCE_SUBMIT.
+ */
+#define I915_PARAM_HAS_EXEC_SUBMIT_FENCE 53
+
+/*
+ * Revision of the i915-perf uAPI. The value returned helps determine what
+ * i915-perf features are available. See drm_i915_perf_property_id.
+ */
+#define I915_PARAM_PERF_REVISION 54
+
+/* Must be kept compact -- no holes and well documented */
+
typedef struct drm_i915_getparam {
__s32 param;
/*
@@ -544,6 +636,7 @@ typedef struct drm_i915_getparam {
#define I915_SETPARAM_TEX_LRU_LOG_GRANULARITY 2
#define I915_SETPARAM_ALLOW_BATCHBUFFER 3
#define I915_SETPARAM_NUM_USED_FENCES 4
+/* Must be kept compact -- no holes */
typedef struct drm_i915_setparam {
int param;
@@ -701,6 +794,37 @@ struct drm_i915_gem_mmap_gtt {
__u64 offset;
};
+struct drm_i915_gem_mmap_offset {
+ /** Handle for the object being mapped. */
+ __u32 handle;
+ __u32 pad;
+ /**
+ * Fake offset to use for subsequent mmap call
+ *
+ * This is a fixed-size type for 32/64 compatibility.
+ */
+ __u64 offset;
+
+ /**
+ * Flags for extended behaviour.
+ *
+ * It is mandatory that one of the MMAP_OFFSET types
+ * (GTT, WC, WB, UC, etc) should be included.
+ */
+ __u64 flags;
+#define I915_MMAP_OFFSET_GTT 0
+#define I915_MMAP_OFFSET_WC 1
+#define I915_MMAP_OFFSET_WB 2
+#define I915_MMAP_OFFSET_UC 3
+
+ /*
+ * Zero-terminated chain of extensions.
+ *
+ * No current extensions defined; mbz.
+ */
+ __u64 extensions;
+};
+
struct drm_i915_gem_set_domain {
/** Handle for the object */
__u32 handle;
@@ -1048,7 +1172,16 @@ struct drm_i915_gem_execbuffer2 {
*/
#define I915_EXEC_FENCE_ARRAY (1<<19)
-#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_ARRAY<<1))
+/*
+ * Setting I915_EXEC_FENCE_SUBMIT implies that lower_32_bits(rsvd2) represent
+ * a sync_file fd to wait upon (in a nonblocking manner) prior to executing
+ * the batch.
+ *
+ * Returns -EINVAL if the sync_file fd cannot be found.
+ */
+#define I915_EXEC_FENCE_SUBMIT (1 << 20)
+
+#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_SUBMIT << 1))
#define I915_EXEC_CONTEXT_ID_MASK (0xffffffff)
#define i915_execbuffer2_set_context_id(eb2, context) \
@@ -1090,32 +1223,34 @@ struct drm_i915_gem_busy {
* as busy may become idle before the ioctl is completed.
*
* Furthermore, if the object is busy, which engine is busy is only
- * provided as a guide. There are race conditions which prevent the
- * report of which engines are busy from being always accurate.
- * However, the converse is not true. If the object is idle, the
- * result of the ioctl, that all engines are idle, is accurate.
+ * provided as a guide and only indirectly by reporting its class
+ * (there may be more than one engine in each class). There are race
+ * conditions which prevent the report of which engines are busy from
+ * being always accurate. However, the converse is not true. If the
+ * object is idle, the result of the ioctl, that all engines are idle,
+ * is accurate.
*
* The returned dword is split into two fields to indicate both
- * the engines on which the object is being read, and the
- * engine on which it is currently being written (if any).
+ * the engine classess on which the object is being read, and the
+ * engine class on which it is currently being written (if any).
*
* The low word (bits 0:15) indicate if the object is being written
* to by any engine (there can only be one, as the GEM implicit
* synchronisation rules force writes to be serialised). Only the
- * engine for the last write is reported.
+ * engine class (offset by 1, I915_ENGINE_CLASS_RENDER is reported as
+ * 1 not 0 etc) for the last write is reported.
*
- * The high word (bits 16:31) are a bitmask of which engines are
- * currently reading from the object. Multiple engines may be
+ * The high word (bits 16:31) are a bitmask of which engines classes
+ * are currently reading from the object. Multiple engines may be
* reading from the object simultaneously.
*
- * The value of each engine is the same as specified in the
- * EXECBUFFER2 ioctl, i.e. I915_EXEC_RENDER, I915_EXEC_BSD etc.
- * Note I915_EXEC_DEFAULT is a symbolic value and is mapped to
- * the I915_EXEC_RENDER engine for execution, and so it is never
+ * The value of each engine class is the same as specified in the
+ * I915_CONTEXT_SET_ENGINES parameter and via perf, i.e.
+ * I915_ENGINE_CLASS_RENDER, I915_ENGINE_CLASS_COPY, etc.
* reported as active itself. Some hardware may have parallel
* execution engines, e.g. multiple media engines, which are
- * mapped to the same identifier in the EXECBUFFER2 ioctl and
- * so are not separately reported for busyness.
+ * mapped to the same class identifier and so are not separately
+ * reported for busyness.
*
* Caveat emptor:
* Only the boolean result of this query is reliable; that is whether
@@ -1382,16 +1517,334 @@ struct drm_i915_gem_wait {
};
struct drm_i915_gem_context_create {
- /* output: id of new context*/
- __u32 ctx_id;
+ __u32 ctx_id; /* output: id of new context*/
__u32 pad;
};
+struct drm_i915_gem_context_create_ext {
+ __u32 ctx_id; /* output: id of new context*/
+ __u32 flags;
+#define I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS (1u << 0)
+#define I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE (1u << 1)
+#define I915_CONTEXT_CREATE_FLAGS_UNKNOWN \
+ (-(I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE << 1))
+ __u64 extensions;
+};
+
+struct drm_i915_gem_context_param {
+ __u32 ctx_id;
+ __u32 size;
+ __u64 param;
+#define I915_CONTEXT_PARAM_BAN_PERIOD 0x1
+#define I915_CONTEXT_PARAM_NO_ZEROMAP 0x2
+#define I915_CONTEXT_PARAM_GTT_SIZE 0x3
+#define I915_CONTEXT_PARAM_NO_ERROR_CAPTURE 0x4
+#define I915_CONTEXT_PARAM_BANNABLE 0x5
+#define I915_CONTEXT_PARAM_PRIORITY 0x6
+#define I915_CONTEXT_MAX_USER_PRIORITY 1023 /* inclusive */
+#define I915_CONTEXT_DEFAULT_PRIORITY 0
+#define I915_CONTEXT_MIN_USER_PRIORITY -1023 /* inclusive */
+ /*
+ * When using the following param, value should be a pointer to
+ * drm_i915_gem_context_param_sseu.
+ */
+#define I915_CONTEXT_PARAM_SSEU 0x7
+
+/*
+ * Not all clients may want to attempt automatic recover of a context after
+ * a hang (for example, some clients may only submit very small incremental
+ * batches relying on known logical state of previous batches which will never
+ * recover correctly and each attempt will hang), and so would prefer that
+ * the context is forever banned instead.
+ *
+ * If set to false (0), after a reset, subsequent (and in flight) rendering
+ * from this context is discarded, and the client will need to create a new
+ * context to use instead.
+ *
+ * If set to true (1), the kernel will automatically attempt to recover the
+ * context by skipping the hanging batch and executing the next batch starting
+ * from the default context state (discarding the incomplete logical context
+ * state lost due to the reset).
+ *
+ * On creation, all new contexts are marked as recoverable.
+ */
+#define I915_CONTEXT_PARAM_RECOVERABLE 0x8
+
+ /*
+ * The id of the associated virtual memory address space (ppGTT) of
+ * this context. Can be retrieved and passed to another context
+ * (on the same fd) for both to use the same ppGTT and so share
+ * address layouts, and avoid reloading the page tables on context
+ * switches between themselves.
+ *
+ * See DRM_I915_GEM_VM_CREATE and DRM_I915_GEM_VM_DESTROY.
+ */
+#define I915_CONTEXT_PARAM_VM 0x9
+
+/*
+ * I915_CONTEXT_PARAM_ENGINES:
+ *
+ * Bind this context to operate on this subset of available engines. Henceforth,
+ * the I915_EXEC_RING selector for DRM_IOCTL_I915_GEM_EXECBUFFER2 operates as
+ * an index into this array of engines; I915_EXEC_DEFAULT selecting engine[0]
+ * and upwards. Slots 0...N are filled in using the specified (class, instance).
+ * Use
+ * engine_class: I915_ENGINE_CLASS_INVALID,
+ * engine_instance: I915_ENGINE_CLASS_INVALID_NONE
+ * to specify a gap in the array that can be filled in later, e.g. by a
+ * virtual engine used for load balancing.
+ *
+ * Setting the number of engines bound to the context to 0, by passing a zero
+ * sized argument, will revert back to default settings.
+ *
+ * See struct i915_context_param_engines.
+ *
+ * Extensions:
+ * i915_context_engines_load_balance (I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE)
+ * i915_context_engines_bond (I915_CONTEXT_ENGINES_EXT_BOND)
+ */
+#define I915_CONTEXT_PARAM_ENGINES 0xa
+
+/*
+ * I915_CONTEXT_PARAM_PERSISTENCE:
+ *
+ * Allow the context and active rendering to survive the process until
+ * completion. Persistence allows fire-and-forget clients to queue up a
+ * bunch of work, hand the output over to a display server and then quit.
+ * If the context is marked as not persistent, upon closing (either via
+ * an explicit DRM_I915_GEM_CONTEXT_DESTROY or implicitly from file closure
+ * or process termination), the context and any outstanding requests will be
+ * cancelled (and exported fences for cancelled requests marked as -EIO).
+ *
+ * By default, new contexts allow persistence.
+ */
+#define I915_CONTEXT_PARAM_PERSISTENCE 0xb
+
+/*
+ * I915_CONTEXT_PARAM_RINGSIZE:
+ *
+ * Sets the size of the CS ringbuffer to use for logical ring contexts. This
+ * applies a limit of how many batches can be queued to HW before the caller
+ * is blocked due to lack of space for more commands.
+ *
+ * Only reliably possible to be set prior to first use, i.e. during
+ * construction. At any later point, the current execution must be flushed as
+ * the ring can only be changed while the context is idle. Note, the ringsize
+ * can be specified as a constructor property, see
+ * I915_CONTEXT_CREATE_EXT_SETPARAM, but can also be set later if required.
+ *
+ * Only applies to the current set of engine and lost when those engines
+ * are replaced by a new mapping (see I915_CONTEXT_PARAM_ENGINES).
+ *
+ * Must be between 4 - 512 KiB, in intervals of page size [4 KiB].
+ * Default is 16 KiB.
+ */
+#define I915_CONTEXT_PARAM_RINGSIZE 0xc
+/* Must be kept compact -- no holes and well documented */
+
+ __u64 value;
+};
+
+/**
+ * Context SSEU programming
+ *
+ * It may be necessary for either functional or performance reason to configure
+ * a context to run with a reduced number of SSEU (where SSEU stands for Slice/
+ * Sub-slice/EU).
+ *
+ * This is done by configuring SSEU configuration using the below
+ * @struct drm_i915_gem_context_param_sseu for every supported engine which
+ * userspace intends to use.
+ *
+ * Not all GPUs or engines support this functionality in which case an error
+ * code -ENODEV will be returned.
+ *
+ * Also, flexibility of possible SSEU configuration permutations varies between
+ * GPU generations and software imposed limitations. Requesting such a
+ * combination will return an error code of -EINVAL.
+ *
+ * NOTE: When perf/OA is active the context's SSEU configuration is ignored in
+ * favour of a single global setting.
+ */
+struct drm_i915_gem_context_param_sseu {
+ /*
+ * Engine class & instance to be configured or queried.
+ */
+ struct i915_engine_class_instance engine;
+
+ /*
+ * Unknown flags must be cleared to zero.
+ */
+ __u32 flags;
+#define I915_CONTEXT_SSEU_FLAG_ENGINE_INDEX (1u << 0)
+
+ /*
+ * Mask of slices to enable for the context. Valid values are a subset
+ * of the bitmask value returned for I915_PARAM_SLICE_MASK.
+ */
+ __u64 slice_mask;
+
+ /*
+ * Mask of subslices to enable for the context. Valid values are a
+ * subset of the bitmask value return by I915_PARAM_SUBSLICE_MASK.
+ */
+ __u64 subslice_mask;
+
+ /*
+ * Minimum/Maximum number of EUs to enable per subslice for the
+ * context. min_eus_per_subslice must be inferior or equal to
+ * max_eus_per_subslice.
+ */
+ __u16 min_eus_per_subslice;
+ __u16 max_eus_per_subslice;
+
+ /*
+ * Unused for now. Must be cleared to zero.
+ */
+ __u32 rsvd;
+};
+
+/*
+ * i915_context_engines_load_balance:
+ *
+ * Enable load balancing across this set of engines.
+ *
+ * Into the I915_EXEC_DEFAULT slot [0], a virtual engine is created that when
+ * used will proxy the execbuffer request onto one of the set of engines
+ * in such a way as to distribute the load evenly across the set.
+ *
+ * The set of engines must be compatible (e.g. the same HW class) as they
+ * will share the same logical GPU context and ring.
+ *
+ * To intermix rendering with the virtual engine and direct rendering onto
+ * the backing engines (bypassing the load balancing proxy), the context must
+ * be defined to use a single timeline for all engines.
+ */
+struct i915_context_engines_load_balance {
+ struct i915_user_extension base;
+
+ __u16 engine_index;
+ __u16 num_siblings;
+ __u32 flags; /* all undefined flags must be zero */
+
+ __u64 mbz64; /* reserved for future use; must be zero */
+
+ struct i915_engine_class_instance engines[0];
+} __attribute__((packed));
+
+#define I915_DEFINE_CONTEXT_ENGINES_LOAD_BALANCE(name__, N__) struct { \
+ struct i915_user_extension base; \
+ __u16 engine_index; \
+ __u16 num_siblings; \
+ __u32 flags; \
+ __u64 mbz64; \
+ struct i915_engine_class_instance engines[N__]; \
+} __attribute__((packed)) name__
+
+/*
+ * i915_context_engines_bond:
+ *
+ * Constructed bonded pairs for execution within a virtual engine.
+ *
+ * All engines are equal, but some are more equal than others. Given
+ * the distribution of resources in the HW, it may be preferable to run
+ * a request on a given subset of engines in parallel to a request on a
+ * specific engine. We enable this selection of engines within a virtual
+ * engine by specifying bonding pairs, for any given master engine we will
+ * only execute on one of the corresponding siblings within the virtual engine.
+ *
+ * To execute a request in parallel on the master engine and a sibling requires
+ * coordination with a I915_EXEC_FENCE_SUBMIT.
+ */
+struct i915_context_engines_bond {
+ struct i915_user_extension base;
+
+ struct i915_engine_class_instance master;
+
+ __u16 virtual_index; /* index of virtual engine in ctx->engines[] */
+ __u16 num_bonds;
+
+ __u64 flags; /* all undefined flags must be zero */
+ __u64 mbz64[4]; /* reserved for future use; must be zero */
+
+ struct i915_engine_class_instance engines[0];
+} __attribute__((packed));
+
+#define I915_DEFINE_CONTEXT_ENGINES_BOND(name__, N__) struct { \
+ struct i915_user_extension base; \
+ struct i915_engine_class_instance master; \
+ __u16 virtual_index; \
+ __u16 num_bonds; \
+ __u64 flags; \
+ __u64 mbz64[4]; \
+ struct i915_engine_class_instance engines[N__]; \
+} __attribute__((packed)) name__
+
+struct i915_context_param_engines {
+ __u64 extensions; /* linked chain of extension blocks, 0 terminates */
+#define I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE 0 /* see i915_context_engines_load_balance */
+#define I915_CONTEXT_ENGINES_EXT_BOND 1 /* see i915_context_engines_bond */
+ struct i915_engine_class_instance engines[0];
+} __attribute__((packed));
+
+#define I915_DEFINE_CONTEXT_PARAM_ENGINES(name__, N__) struct { \
+ __u64 extensions; \
+ struct i915_engine_class_instance engines[N__]; \
+} __attribute__((packed)) name__
+
+struct drm_i915_gem_context_create_ext_setparam {
+#define I915_CONTEXT_CREATE_EXT_SETPARAM 0
+ struct i915_user_extension base;
+ struct drm_i915_gem_context_param param;
+};
+
+struct drm_i915_gem_context_create_ext_clone {
+#define I915_CONTEXT_CREATE_EXT_CLONE 1
+ struct i915_user_extension base;
+ __u32 clone_id;
+ __u32 flags;
+#define I915_CONTEXT_CLONE_ENGINES (1u << 0)
+#define I915_CONTEXT_CLONE_FLAGS (1u << 1)
+#define I915_CONTEXT_CLONE_SCHEDATTR (1u << 2)
+#define I915_CONTEXT_CLONE_SSEU (1u << 3)
+#define I915_CONTEXT_CLONE_TIMELINE (1u << 4)
+#define I915_CONTEXT_CLONE_VM (1u << 5)
+#define I915_CONTEXT_CLONE_UNKNOWN -(I915_CONTEXT_CLONE_VM << 1)
+ __u64 rsvd;
+};
+
struct drm_i915_gem_context_destroy {
__u32 ctx_id;
__u32 pad;
};
+/*
+ * DRM_I915_GEM_VM_CREATE -
+ *
+ * Create a new virtual memory address space (ppGTT) for use within a context
+ * on the same file. Extensions can be provided to configure exactly how the
+ * address space is setup upon creation.
+ *
+ * The id of new VM (bound to the fd) for use with I915_CONTEXT_PARAM_VM is
+ * returned in the outparam @id.
+ *
+ * No flags are defined, with all bits reserved and must be zero.
+ *
+ * An extension chain maybe provided, starting with @extensions, and terminated
+ * by the @next_extension being 0. Currently, no extensions are defined.
+ *
+ * DRM_I915_GEM_VM_DESTROY -
+ *
+ * Destroys a previously created VM id, specified in @id.
+ *
+ * No extensions or flags are allowed currently, and so must be zero.
+ */
+struct drm_i915_gem_vm_control {
+ __u64 extensions;
+ __u32 flags;
+ __u32 vm_id;
+};
+
struct drm_i915_reg_read {
/*
* Register offset.
@@ -1404,6 +1857,7 @@ struct drm_i915_reg_read {
__u64 val; /* Return value */
};
+
/* Known registers:
*
* Render engine timestamp - 0x2358 + 64bit - gen7+
@@ -1443,22 +1897,6 @@ struct drm_i915_gem_userptr {
__u32 handle;
};
-struct drm_i915_gem_context_param {
- __u32 ctx_id;
- __u32 size;
- __u64 param;
-#define I915_CONTEXT_PARAM_BAN_PERIOD 0x1
-#define I915_CONTEXT_PARAM_NO_ZEROMAP 0x2
-#define I915_CONTEXT_PARAM_GTT_SIZE 0x3
-#define I915_CONTEXT_PARAM_NO_ERROR_CAPTURE 0x4
-#define I915_CONTEXT_PARAM_BANNABLE 0x5
-#define I915_CONTEXT_PARAM_PRIORITY 0x6
-#define I915_CONTEXT_MAX_USER_PRIORITY 1023 /* inclusive */
-#define I915_CONTEXT_DEFAULT_PRIORITY 0
-#define I915_CONTEXT_MIN_USER_PRIORITY -1023 /* inclusive */
- __u64 value;
-};
-
enum drm_i915_oa_format {
I915_OA_FORMAT_A13 = 1, /* HSW only */
I915_OA_FORMAT_A29, /* HSW only */
@@ -1481,23 +1919,31 @@ enum drm_i915_perf_property_id {
* Open the stream for a specific context handle (as used with
* execbuffer2). A stream opened for a specific context this way
* won't typically require root privileges.
+ *
+ * This property is available in perf revision 1.
*/
DRM_I915_PERF_PROP_CTX_HANDLE = 1,
/**
* A value of 1 requests the inclusion of raw OA unit reports as
* part of stream samples.
+ *
+ * This property is available in perf revision 1.
*/
DRM_I915_PERF_PROP_SAMPLE_OA,
/**
* The value specifies which set of OA unit metrics should be
* be configured, defining the contents of any OA unit reports.
+ *
+ * This property is available in perf revision 1.
*/
DRM_I915_PERF_PROP_OA_METRICS_SET,
/**
* The value specifies the size and layout of OA unit reports.
+ *
+ * This property is available in perf revision 1.
*/
DRM_I915_PERF_PROP_OA_FORMAT,
@@ -1507,9 +1953,22 @@ enum drm_i915_perf_property_id {
* from this exponent as follows:
*
* 80ns * 2^(period_exponent + 1)
+ *
+ * This property is available in perf revision 1.
*/
DRM_I915_PERF_PROP_OA_EXPONENT,
+ /**
+ * Specifying this property is only valid when specify a context to
+ * filter with DRM_I915_PERF_PROP_CTX_HANDLE. Specifying this property
+ * will hold preemption of the particular context we want to gather
+ * performance data about. The execbuf2 submissions must include a
+ * drm_i915_gem_execbuffer_ext_perf parameter for this to apply.
+ *
+ * This property is available in perf revision 3.
+ */
+ DRM_I915_PERF_PROP_HOLD_PREEMPTION,
+
DRM_I915_PERF_PROP_MAX /* non-ABI */
};
@@ -1538,6 +1997,8 @@ struct drm_i915_perf_open_param {
* to close and re-open a stream with the same configuration.
*
* It's undefined whether any pending data for the stream will be lost.
+ *
+ * This ioctl is available in perf revision 1.
*/
#define I915_PERF_IOCTL_ENABLE _IO('i', 0x0)
@@ -1545,10 +2006,25 @@ struct drm_i915_perf_open_param {
* Disable data capture for a stream.
*
* It is an error to try and read a stream that is disabled.
+ *
+ * This ioctl is available in perf revision 1.
*/
#define I915_PERF_IOCTL_DISABLE _IO('i', 0x1)
/**
+ * Change metrics_set captured by a stream.
+ *
+ * If the stream is bound to a specific context, the configuration change
+ * will performed inline with that context such that it takes effect before
+ * the next execbuf submission.
+ *
+ * Returns the previously bound metrics set id, or a negative error code.
+ *
+ * This ioctl is available in perf revision 2.
+ */
+#define I915_PERF_IOCTL_CONFIG _IO('i', 0x2)
+
+/**
* Common to all i915 perf records
*/
struct drm_i915_perf_record_header {
@@ -1620,6 +2096,9 @@ struct drm_i915_perf_oa_config {
struct drm_i915_query_item {
__u64 query_id;
#define DRM_I915_QUERY_TOPOLOGY_INFO 1
+#define DRM_I915_QUERY_ENGINE_INFO 2
+#define DRM_I915_QUERY_PERF_CONFIG 3
+/* Must be kept compact -- no holes and well documented */
/*
* When set to zero by userspace, this is filled with the size of the
@@ -1630,9 +2109,18 @@ struct drm_i915_query_item {
__s32 length;
/*
- * Unused for now. Must be cleared to zero.
+ * When query_id == DRM_I915_QUERY_TOPOLOGY_INFO, must be 0.
+ *
+ * When query_id == DRM_I915_QUERY_PERF_CONFIG, must be one of the
+ * following :
+ * - DRM_I915_QUERY_PERF_CONFIG_LIST
+ * - DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID
+ * - DRM_I915_QUERY_PERF_CONFIG_FOR_UUID
*/
__u32 flags;
+#define DRM_I915_QUERY_PERF_CONFIG_LIST 1
+#define DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID 2
+#define DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_ID 3
/*
* Data will be written at the location pointed by data_ptr when the
@@ -1668,8 +2156,10 @@ struct drm_i915_query {
* (data[X / 8] >> (X % 8)) & 1
*
* - the subslice mask for each slice with one bit per subslice telling
- * whether a subslice is available. The availability of subslice Y in slice
- * X can be queried with the following formula :
+ * whether a subslice is available. Gen12 has dual-subslices, which are
+ * similar to two gen11 subslices. For gen12, this array represents dual-
+ * subslices. The availability of subslice Y in slice X can be queried
+ * with the following formula :
*
* (data[subslice_offset +
* X * subslice_stride +
@@ -1717,6 +2207,97 @@ struct drm_i915_query_topology_info {
__u8 data[];
};
+/**
+ * struct drm_i915_engine_info
+ *
+ * Describes one engine and it's capabilities as known to the driver.
+ */
+struct drm_i915_engine_info {
+ /** Engine class and instance. */
+ struct i915_engine_class_instance engine;
+
+ /** Reserved field. */
+ __u32 rsvd0;
+
+ /** Engine flags. */
+ __u64 flags;
+
+ /** Capabilities of this engine. */
+ __u64 capabilities;
+#define I915_VIDEO_CLASS_CAPABILITY_HEVC (1 << 0)
+#define I915_VIDEO_AND_ENHANCE_CLASS_CAPABILITY_SFC (1 << 1)
+
+ /** Reserved fields. */
+ __u64 rsvd1[4];
+};
+
+/**
+ * struct drm_i915_query_engine_info
+ *
+ * Engine info query enumerates all engines known to the driver by filling in
+ * an array of struct drm_i915_engine_info structures.
+ */
+struct drm_i915_query_engine_info {
+ /** Number of struct drm_i915_engine_info structs following. */
+ __u32 num_engines;
+
+ /** MBZ */
+ __u32 rsvd[3];
+
+ /** Marker for drm_i915_engine_info structures. */
+ struct drm_i915_engine_info engines[];
+};
+
+/*
+ * Data written by the kernel with query DRM_I915_QUERY_PERF_CONFIG.
+ */
+struct drm_i915_query_perf_config {
+ union {
+ /*
+ * When query_item.flags == DRM_I915_QUERY_PERF_CONFIG_LIST, i915 sets
+ * this fields to the number of configurations available.
+ */
+ __u64 n_configs;
+
+ /*
+ * When query_id == DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_ID,
+ * i915 will use the value in this field as configuration
+ * identifier to decide what data to write into config_ptr.
+ */
+ __u64 config;
+
+ /*
+ * When query_id == DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID,
+ * i915 will use the value in this field as configuration
+ * identifier to decide what data to write into config_ptr.
+ *
+ * String formatted like "%08x-%04x-%04x-%04x-%012x"
+ */
+ char uuid[36];
+ };
+
+ /*
+ * Unused for now. Must be cleared to zero.
+ */
+ __u32 flags;
+
+ /*
+ * When query_item.flags == DRM_I915_QUERY_PERF_CONFIG_LIST, i915 will
+ * write an array of __u64 of configuration identifiers.
+ *
+ * When query_item.flags == DRM_I915_QUERY_PERF_CONFIG_DATA, i915 will
+ * write a struct drm_i915_perf_oa_config. If the following fields of
+ * drm_i915_perf_oa_config are set not set to 0, i915 will write into
+ * the associated pointers the values of submitted when the
+ * configuration was created :
+ *
+ * - n_mux_regs
+ * - n_boolean_regs
+ * - n_flex_regs
+ */
+ __u8 data[];
+};
+
#if defined(__cplusplus)
}
#endif
diff --git a/sys/dev/pci/drm/include/uapi/drm/radeon_drm.h b/sys/dev/pci/drm/include/uapi/drm/radeon_drm.h
index ddc8f23b730..490a59cc453 100644
--- a/sys/dev/pci/drm/include/uapi/drm/radeon_drm.h
+++ b/sys/dev/pci/drm/include/uapi/drm/radeon_drm.h
@@ -765,7 +765,7 @@ typedef struct drm_radeon_irq_wait {
typedef struct drm_radeon_setparam {
unsigned int param;
- int64_t value;
+ __s64 value;
} drm_radeon_setparam_t;
#define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */
diff --git a/sys/dev/pci/drm/include/uapi/linux/ioctl.h b/sys/dev/pci/drm/include/uapi/linux/ioctl.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sys/dev/pci/drm/include/uapi/linux/ioctl.h
diff --git a/sys/dev/pci/drm/include/uapi/linux/kfd_ioctl.h b/sys/dev/pci/drm/include/uapi/linux/kfd_ioctl.h
new file mode 100644
index 00000000000..20917c59f39
--- /dev/null
+++ b/sys/dev/pci/drm/include/uapi/linux/kfd_ioctl.h
@@ -0,0 +1,535 @@
+/*
+ * Copyright 2014 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef KFD_IOCTL_H_INCLUDED
+#define KFD_IOCTL_H_INCLUDED
+
+#include <drm/drm.h>
+#include <linux/ioctl.h>
+
+#define KFD_IOCTL_MAJOR_VERSION 1
+#define KFD_IOCTL_MINOR_VERSION 1
+
+struct kfd_ioctl_get_version_args {
+ __u32 major_version; /* from KFD */
+ __u32 minor_version; /* from KFD */
+};
+
+/* For kfd_ioctl_create_queue_args.queue_type. */
+#define KFD_IOC_QUEUE_TYPE_COMPUTE 0x0
+#define KFD_IOC_QUEUE_TYPE_SDMA 0x1
+#define KFD_IOC_QUEUE_TYPE_COMPUTE_AQL 0x2
+#define KFD_IOC_QUEUE_TYPE_SDMA_XGMI 0x3
+
+#define KFD_MAX_QUEUE_PERCENTAGE 100
+#define KFD_MAX_QUEUE_PRIORITY 15
+
+struct kfd_ioctl_create_queue_args {
+ __u64 ring_base_address; /* to KFD */
+ __u64 write_pointer_address; /* from KFD */
+ __u64 read_pointer_address; /* from KFD */
+ __u64 doorbell_offset; /* from KFD */
+
+ __u32 ring_size; /* to KFD */
+ __u32 gpu_id; /* to KFD */
+ __u32 queue_type; /* to KFD */
+ __u32 queue_percentage; /* to KFD */
+ __u32 queue_priority; /* to KFD */
+ __u32 queue_id; /* from KFD */
+
+ __u64 eop_buffer_address; /* to KFD */
+ __u64 eop_buffer_size; /* to KFD */
+ __u64 ctx_save_restore_address; /* to KFD */
+ __u32 ctx_save_restore_size; /* to KFD */
+ __u32 ctl_stack_size; /* to KFD */
+};
+
+struct kfd_ioctl_destroy_queue_args {
+ __u32 queue_id; /* to KFD */
+ __u32 pad;
+};
+
+struct kfd_ioctl_update_queue_args {
+ __u64 ring_base_address; /* to KFD */
+
+ __u32 queue_id; /* to KFD */
+ __u32 ring_size; /* to KFD */
+ __u32 queue_percentage; /* to KFD */
+ __u32 queue_priority; /* to KFD */
+};
+
+struct kfd_ioctl_set_cu_mask_args {
+ __u32 queue_id; /* to KFD */
+ __u32 num_cu_mask; /* to KFD */
+ __u64 cu_mask_ptr; /* to KFD */
+};
+
+struct kfd_ioctl_get_queue_wave_state_args {
+ __u64 ctl_stack_address; /* to KFD */
+ __u32 ctl_stack_used_size; /* from KFD */
+ __u32 save_area_used_size; /* from KFD */
+ __u32 queue_id; /* to KFD */
+ __u32 pad;
+};
+
+/* For kfd_ioctl_set_memory_policy_args.default_policy and alternate_policy */
+#define KFD_IOC_CACHE_POLICY_COHERENT 0
+#define KFD_IOC_CACHE_POLICY_NONCOHERENT 1
+
+struct kfd_ioctl_set_memory_policy_args {
+ __u64 alternate_aperture_base; /* to KFD */
+ __u64 alternate_aperture_size; /* to KFD */
+
+ __u32 gpu_id; /* to KFD */
+ __u32 default_policy; /* to KFD */
+ __u32 alternate_policy; /* to KFD */
+ __u32 pad;
+};
+
+/*
+ * All counters are monotonic. They are used for profiling of compute jobs.
+ * The profiling is done by userspace.
+ *
+ * In case of GPU reset, the counter should not be affected.
+ */
+
+struct kfd_ioctl_get_clock_counters_args {
+ __u64 gpu_clock_counter; /* from KFD */
+ __u64 cpu_clock_counter; /* from KFD */
+ __u64 system_clock_counter; /* from KFD */
+ __u64 system_clock_freq; /* from KFD */
+
+ __u32 gpu_id; /* to KFD */
+ __u32 pad;
+};
+
+struct kfd_process_device_apertures {
+ __u64 lds_base; /* from KFD */
+ __u64 lds_limit; /* from KFD */
+ __u64 scratch_base; /* from KFD */
+ __u64 scratch_limit; /* from KFD */
+ __u64 gpuvm_base; /* from KFD */
+ __u64 gpuvm_limit; /* from KFD */
+ __u32 gpu_id; /* from KFD */
+ __u32 pad;
+};
+
+/*
+ * AMDKFD_IOC_GET_PROCESS_APERTURES is deprecated. Use
+ * AMDKFD_IOC_GET_PROCESS_APERTURES_NEW instead, which supports an
+ * unlimited number of GPUs.
+ */
+#define NUM_OF_SUPPORTED_GPUS 7
+struct kfd_ioctl_get_process_apertures_args {
+ struct kfd_process_device_apertures
+ process_apertures[NUM_OF_SUPPORTED_GPUS];/* from KFD */
+
+ /* from KFD, should be in the range [1 - NUM_OF_SUPPORTED_GPUS] */
+ __u32 num_of_nodes;
+ __u32 pad;
+};
+
+struct kfd_ioctl_get_process_apertures_new_args {
+ /* User allocated. Pointer to struct kfd_process_device_apertures
+ * filled in by Kernel
+ */
+ __u64 kfd_process_device_apertures_ptr;
+ /* to KFD - indicates amount of memory present in
+ * kfd_process_device_apertures_ptr
+ * from KFD - Number of entries filled by KFD.
+ */
+ __u32 num_of_nodes;
+ __u32 pad;
+};
+
+#define MAX_ALLOWED_NUM_POINTS 100
+#define MAX_ALLOWED_AW_BUFF_SIZE 4096
+#define MAX_ALLOWED_WAC_BUFF_SIZE 128
+
+struct kfd_ioctl_dbg_register_args {
+ __u32 gpu_id; /* to KFD */
+ __u32 pad;
+};
+
+struct kfd_ioctl_dbg_unregister_args {
+ __u32 gpu_id; /* to KFD */
+ __u32 pad;
+};
+
+struct kfd_ioctl_dbg_address_watch_args {
+ __u64 content_ptr; /* a pointer to the actual content */
+ __u32 gpu_id; /* to KFD */
+ __u32 buf_size_in_bytes; /*including gpu_id and buf_size */
+};
+
+struct kfd_ioctl_dbg_wave_control_args {
+ __u64 content_ptr; /* a pointer to the actual content */
+ __u32 gpu_id; /* to KFD */
+ __u32 buf_size_in_bytes; /*including gpu_id and buf_size */
+};
+
+/* Matching HSA_EVENTTYPE */
+#define KFD_IOC_EVENT_SIGNAL 0
+#define KFD_IOC_EVENT_NODECHANGE 1
+#define KFD_IOC_EVENT_DEVICESTATECHANGE 2
+#define KFD_IOC_EVENT_HW_EXCEPTION 3
+#define KFD_IOC_EVENT_SYSTEM_EVENT 4
+#define KFD_IOC_EVENT_DEBUG_EVENT 5
+#define KFD_IOC_EVENT_PROFILE_EVENT 6
+#define KFD_IOC_EVENT_QUEUE_EVENT 7
+#define KFD_IOC_EVENT_MEMORY 8
+
+#define KFD_IOC_WAIT_RESULT_COMPLETE 0
+#define KFD_IOC_WAIT_RESULT_TIMEOUT 1
+#define KFD_IOC_WAIT_RESULT_FAIL 2
+
+#define KFD_SIGNAL_EVENT_LIMIT 4096
+
+/* For kfd_event_data.hw_exception_data.reset_type. */
+#define KFD_HW_EXCEPTION_WHOLE_GPU_RESET 0
+#define KFD_HW_EXCEPTION_PER_ENGINE_RESET 1
+
+/* For kfd_event_data.hw_exception_data.reset_cause. */
+#define KFD_HW_EXCEPTION_GPU_HANG 0
+#define KFD_HW_EXCEPTION_ECC 1
+
+/* For kfd_hsa_memory_exception_data.ErrorType */
+#define KFD_MEM_ERR_NO_RAS 0
+#define KFD_MEM_ERR_SRAM_ECC 1
+#define KFD_MEM_ERR_POISON_CONSUMED 2
+#define KFD_MEM_ERR_GPU_HANG 3
+
+struct kfd_ioctl_create_event_args {
+ __u64 event_page_offset; /* from KFD */
+ __u32 event_trigger_data; /* from KFD - signal events only */
+ __u32 event_type; /* to KFD */
+ __u32 auto_reset; /* to KFD */
+ __u32 node_id; /* to KFD - only valid for certain
+ event types */
+ __u32 event_id; /* from KFD */
+ __u32 event_slot_index; /* from KFD */
+};
+
+struct kfd_ioctl_destroy_event_args {
+ __u32 event_id; /* to KFD */
+ __u32 pad;
+};
+
+struct kfd_ioctl_set_event_args {
+ __u32 event_id; /* to KFD */
+ __u32 pad;
+};
+
+struct kfd_ioctl_reset_event_args {
+ __u32 event_id; /* to KFD */
+ __u32 pad;
+};
+
+struct kfd_memory_exception_failure {
+ __u32 NotPresent; /* Page not present or supervisor privilege */
+ __u32 ReadOnly; /* Write access to a read-only page */
+ __u32 NoExecute; /* Execute access to a page marked NX */
+ __u32 imprecise; /* Can't determine the exact fault address */
+};
+
+/* memory exception data*/
+struct kfd_hsa_memory_exception_data {
+ struct kfd_memory_exception_failure failure;
+ __u64 va;
+ __u32 gpu_id;
+ __u32 ErrorType; /* 0 = no RAS error,
+ * 1 = ECC_SRAM,
+ * 2 = Link_SYNFLOOD (poison),
+ * 3 = GPU hang (not attributable to a specific cause),
+ * other values reserved
+ */
+};
+
+/* hw exception data */
+struct kfd_hsa_hw_exception_data {
+ __u32 reset_type;
+ __u32 reset_cause;
+ __u32 memory_lost;
+ __u32 gpu_id;
+};
+
+/* Event data */
+struct kfd_event_data {
+ union {
+ struct kfd_hsa_memory_exception_data memory_exception_data;
+ struct kfd_hsa_hw_exception_data hw_exception_data;
+ }; /* From KFD */
+ __u64 kfd_event_data_ext; /* pointer to an extension structure
+ for future exception types */
+ __u32 event_id; /* to KFD */
+ __u32 pad;
+};
+
+struct kfd_ioctl_wait_events_args {
+ __u64 events_ptr; /* pointed to struct
+ kfd_event_data array, to KFD */
+ __u32 num_events; /* to KFD */
+ __u32 wait_for_all; /* to KFD */
+ __u32 timeout; /* to KFD */
+ __u32 wait_result; /* from KFD */
+};
+
+struct kfd_ioctl_set_scratch_backing_va_args {
+ __u64 va_addr; /* to KFD */
+ __u32 gpu_id; /* to KFD */
+ __u32 pad;
+};
+
+struct kfd_ioctl_get_tile_config_args {
+ /* to KFD: pointer to tile array */
+ __u64 tile_config_ptr;
+ /* to KFD: pointer to macro tile array */
+ __u64 macro_tile_config_ptr;
+ /* to KFD: array size allocated by user mode
+ * from KFD: array size filled by kernel
+ */
+ __u32 num_tile_configs;
+ /* to KFD: array size allocated by user mode
+ * from KFD: array size filled by kernel
+ */
+ __u32 num_macro_tile_configs;
+
+ __u32 gpu_id; /* to KFD */
+ __u32 gb_addr_config; /* from KFD */
+ __u32 num_banks; /* from KFD */
+ __u32 num_ranks; /* from KFD */
+ /* struct size can be extended later if needed
+ * without breaking ABI compatibility
+ */
+};
+
+struct kfd_ioctl_set_trap_handler_args {
+ __u64 tba_addr; /* to KFD */
+ __u64 tma_addr; /* to KFD */
+ __u32 gpu_id; /* to KFD */
+ __u32 pad;
+};
+
+struct kfd_ioctl_acquire_vm_args {
+ __u32 drm_fd; /* to KFD */
+ __u32 gpu_id; /* to KFD */
+};
+
+/* Allocation flags: memory types */
+#define KFD_IOC_ALLOC_MEM_FLAGS_VRAM (1 << 0)
+#define KFD_IOC_ALLOC_MEM_FLAGS_GTT (1 << 1)
+#define KFD_IOC_ALLOC_MEM_FLAGS_USERPTR (1 << 2)
+#define KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL (1 << 3)
+#define KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP (1 << 4)
+/* Allocation flags: attributes/access options */
+#define KFD_IOC_ALLOC_MEM_FLAGS_WRITABLE (1 << 31)
+#define KFD_IOC_ALLOC_MEM_FLAGS_EXECUTABLE (1 << 30)
+#define KFD_IOC_ALLOC_MEM_FLAGS_PUBLIC (1 << 29)
+#define KFD_IOC_ALLOC_MEM_FLAGS_NO_SUBSTITUTE (1 << 28)
+#define KFD_IOC_ALLOC_MEM_FLAGS_AQL_QUEUE_MEM (1 << 27)
+#define KFD_IOC_ALLOC_MEM_FLAGS_COHERENT (1 << 26)
+
+/* Allocate memory for later SVM (shared virtual memory) mapping.
+ *
+ * @va_addr: virtual address of the memory to be allocated
+ * all later mappings on all GPUs will use this address
+ * @size: size in bytes
+ * @handle: buffer handle returned to user mode, used to refer to
+ * this allocation for mapping, unmapping and freeing
+ * @mmap_offset: for CPU-mapping the allocation by mmapping a render node
+ * for userptrs this is overloaded to specify the CPU address
+ * @gpu_id: device identifier
+ * @flags: memory type and attributes. See KFD_IOC_ALLOC_MEM_FLAGS above
+ */
+struct kfd_ioctl_alloc_memory_of_gpu_args {
+ __u64 va_addr; /* to KFD */
+ __u64 size; /* to KFD */
+ __u64 handle; /* from KFD */
+ __u64 mmap_offset; /* to KFD (userptr), from KFD (mmap offset) */
+ __u32 gpu_id; /* to KFD */
+ __u32 flags;
+};
+
+/* Free memory allocated with kfd_ioctl_alloc_memory_of_gpu
+ *
+ * @handle: memory handle returned by alloc
+ */
+struct kfd_ioctl_free_memory_of_gpu_args {
+ __u64 handle; /* to KFD */
+};
+
+/* Map memory to one or more GPUs
+ *
+ * @handle: memory handle returned by alloc
+ * @device_ids_array_ptr: array of gpu_ids (__u32 per device)
+ * @n_devices: number of devices in the array
+ * @n_success: number of devices mapped successfully
+ *
+ * @n_success returns information to the caller how many devices from
+ * the start of the array have mapped the buffer successfully. It can
+ * be passed into a subsequent retry call to skip those devices. For
+ * the first call the caller should initialize it to 0.
+ *
+ * If the ioctl completes with return code 0 (success), n_success ==
+ * n_devices.
+ */
+struct kfd_ioctl_map_memory_to_gpu_args {
+ __u64 handle; /* to KFD */
+ __u64 device_ids_array_ptr; /* to KFD */
+ __u32 n_devices; /* to KFD */
+ __u32 n_success; /* to/from KFD */
+};
+
+/* Unmap memory from one or more GPUs
+ *
+ * same arguments as for mapping
+ */
+struct kfd_ioctl_unmap_memory_from_gpu_args {
+ __u64 handle; /* to KFD */
+ __u64 device_ids_array_ptr; /* to KFD */
+ __u32 n_devices; /* to KFD */
+ __u32 n_success; /* to/from KFD */
+};
+
+struct kfd_ioctl_get_dmabuf_info_args {
+ __u64 size; /* from KFD */
+ __u64 metadata_ptr; /* to KFD */
+ __u32 metadata_size; /* to KFD (space allocated by user)
+ * from KFD (actual metadata size)
+ */
+ __u32 gpu_id; /* from KFD */
+ __u32 flags; /* from KFD (KFD_IOC_ALLOC_MEM_FLAGS) */
+ __u32 dmabuf_fd; /* to KFD */
+};
+
+struct kfd_ioctl_import_dmabuf_args {
+ __u64 va_addr; /* to KFD */
+ __u64 handle; /* from KFD */
+ __u32 gpu_id; /* to KFD */
+ __u32 dmabuf_fd; /* to KFD */
+};
+
+/* Register offset inside the remapped mmio page
+ */
+enum kfd_mmio_remap {
+ KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL = 0,
+ KFD_MMIO_REMAP_HDP_REG_FLUSH_CNTL = 4,
+};
+
+#define AMDKFD_IOCTL_BASE 'K'
+#define AMDKFD_IO(nr) _IO(AMDKFD_IOCTL_BASE, nr)
+#define AMDKFD_IOR(nr, type) _IOR(AMDKFD_IOCTL_BASE, nr, type)
+#define AMDKFD_IOW(nr, type) _IOW(AMDKFD_IOCTL_BASE, nr, type)
+#define AMDKFD_IOWR(nr, type) _IOWR(AMDKFD_IOCTL_BASE, nr, type)
+
+#define AMDKFD_IOC_GET_VERSION \
+ AMDKFD_IOR(0x01, struct kfd_ioctl_get_version_args)
+
+#define AMDKFD_IOC_CREATE_QUEUE \
+ AMDKFD_IOWR(0x02, struct kfd_ioctl_create_queue_args)
+
+#define AMDKFD_IOC_DESTROY_QUEUE \
+ AMDKFD_IOWR(0x03, struct kfd_ioctl_destroy_queue_args)
+
+#define AMDKFD_IOC_SET_MEMORY_POLICY \
+ AMDKFD_IOW(0x04, struct kfd_ioctl_set_memory_policy_args)
+
+#define AMDKFD_IOC_GET_CLOCK_COUNTERS \
+ AMDKFD_IOWR(0x05, struct kfd_ioctl_get_clock_counters_args)
+
+#define AMDKFD_IOC_GET_PROCESS_APERTURES \
+ AMDKFD_IOR(0x06, struct kfd_ioctl_get_process_apertures_args)
+
+#define AMDKFD_IOC_UPDATE_QUEUE \
+ AMDKFD_IOW(0x07, struct kfd_ioctl_update_queue_args)
+
+#define AMDKFD_IOC_CREATE_EVENT \
+ AMDKFD_IOWR(0x08, struct kfd_ioctl_create_event_args)
+
+#define AMDKFD_IOC_DESTROY_EVENT \
+ AMDKFD_IOW(0x09, struct kfd_ioctl_destroy_event_args)
+
+#define AMDKFD_IOC_SET_EVENT \
+ AMDKFD_IOW(0x0A, struct kfd_ioctl_set_event_args)
+
+#define AMDKFD_IOC_RESET_EVENT \
+ AMDKFD_IOW(0x0B, struct kfd_ioctl_reset_event_args)
+
+#define AMDKFD_IOC_WAIT_EVENTS \
+ AMDKFD_IOWR(0x0C, struct kfd_ioctl_wait_events_args)
+
+#define AMDKFD_IOC_DBG_REGISTER \
+ AMDKFD_IOW(0x0D, struct kfd_ioctl_dbg_register_args)
+
+#define AMDKFD_IOC_DBG_UNREGISTER \
+ AMDKFD_IOW(0x0E, struct kfd_ioctl_dbg_unregister_args)
+
+#define AMDKFD_IOC_DBG_ADDRESS_WATCH \
+ AMDKFD_IOW(0x0F, struct kfd_ioctl_dbg_address_watch_args)
+
+#define AMDKFD_IOC_DBG_WAVE_CONTROL \
+ AMDKFD_IOW(0x10, struct kfd_ioctl_dbg_wave_control_args)
+
+#define AMDKFD_IOC_SET_SCRATCH_BACKING_VA \
+ AMDKFD_IOWR(0x11, struct kfd_ioctl_set_scratch_backing_va_args)
+
+#define AMDKFD_IOC_GET_TILE_CONFIG \
+ AMDKFD_IOWR(0x12, struct kfd_ioctl_get_tile_config_args)
+
+#define AMDKFD_IOC_SET_TRAP_HANDLER \
+ AMDKFD_IOW(0x13, struct kfd_ioctl_set_trap_handler_args)
+
+#define AMDKFD_IOC_GET_PROCESS_APERTURES_NEW \
+ AMDKFD_IOWR(0x14, \
+ struct kfd_ioctl_get_process_apertures_new_args)
+
+#define AMDKFD_IOC_ACQUIRE_VM \
+ AMDKFD_IOW(0x15, struct kfd_ioctl_acquire_vm_args)
+
+#define AMDKFD_IOC_ALLOC_MEMORY_OF_GPU \
+ AMDKFD_IOWR(0x16, struct kfd_ioctl_alloc_memory_of_gpu_args)
+
+#define AMDKFD_IOC_FREE_MEMORY_OF_GPU \
+ AMDKFD_IOW(0x17, struct kfd_ioctl_free_memory_of_gpu_args)
+
+#define AMDKFD_IOC_MAP_MEMORY_TO_GPU \
+ AMDKFD_IOWR(0x18, struct kfd_ioctl_map_memory_to_gpu_args)
+
+#define AMDKFD_IOC_UNMAP_MEMORY_FROM_GPU \
+ AMDKFD_IOWR(0x19, struct kfd_ioctl_unmap_memory_from_gpu_args)
+
+#define AMDKFD_IOC_SET_CU_MASK \
+ AMDKFD_IOW(0x1A, struct kfd_ioctl_set_cu_mask_args)
+
+#define AMDKFD_IOC_GET_QUEUE_WAVE_STATE \
+ AMDKFD_IOWR(0x1B, struct kfd_ioctl_get_queue_wave_state_args)
+
+#define AMDKFD_IOC_GET_DMABUF_INFO \
+ AMDKFD_IOWR(0x1C, struct kfd_ioctl_get_dmabuf_info_args)
+
+#define AMDKFD_IOC_IMPORT_DMABUF \
+ AMDKFD_IOWR(0x1D, struct kfd_ioctl_import_dmabuf_args)
+
+#define AMDKFD_COMMAND_START 0x01
+#define AMDKFD_COMMAND_END 0x1E
+
+#endif
diff --git a/sys/dev/pci/drm/include/video/mipi_display.h b/sys/dev/pci/drm/include/video/mipi_display.h
index 7b303a62f81..1e54e64ced8 100644
--- a/sys/dev/pci/drm/include/video/mipi_display.h
+++ b/sys/dev/pci/drm/include/video/mipi_display.h
@@ -7,6 +7,8 @@
#define MIPI_DSI_V_SYNC_END 0x11
#define MIPI_DSI_H_SYNC_START 0x21
#define MIPI_DSI_H_SYNC_END 0x31
+#define MIPI_DSI_COMPRESSION_MODE 0x07
+#define MIPI_DSI_END_OF_TRANSMISSION 0x08
#define MIPI_DSI_COLOR_MODE_OFF 0x02
#define MIPI_DSI_COLOR_MODE_ON 0x12
#define MIPI_DSI_SHUTDOWN_PERIPHERAL 0x22
@@ -20,14 +22,14 @@
#define MIPI_DSI_DCS_SHORT_WRITE 0x05
#define MIPI_DSI_DCS_SHORT_WRITE_PARAM 0x15
#define MIPI_DSI_DCS_READ 0x06
-#define MIPI_DSI_DCS_COMPRESSION_MODE 0x07
-#define MIPI_DSI_PPS_LONG_WRITE 0x0a
+#define MIPI_DSI_EXECUTE_QUEUE 0x16
#define MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE 0x37
-#define MIPI_DSI_END_OF_TRANSMISSION 0x08
#define MIPI_DSI_NULL_PACKET 0x09
#define MIPI_DSI_BLANKING_PACKET 0x19
#define MIPI_DSI_GENERIC_LONG_WRITE 0x29
#define MIPI_DSI_DCS_LONG_WRITE 0x39
+#define MIPI_DSI_PICTURE_PARAMETER_SET 0x0a
+#define MIPI_DSI_COMPRESSED_PIXEL_STREAM 0x0b
#define MIPI_DSI_LOOSELY_PACKED_PIXEL_STREAM_YCBCR20 0x0c
#define MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR24 0x1c
#define MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16 0x2c