Compare commits

...
Author SHA1 Message Date
Leency ecd62148de drivers/video/drm: add drm_encoder_slave.c for nouveau
Test PR / Build (ru_RU) (pull_request) Successful in 2m56s
Test PR / Build (es_ES) (pull_request) Successful in 3m2s
Test PR / Build (en_US) (pull_request) Successful in 3m8s
The nouveau port builds it with the DRM core: dispnv04 drives its TV
and TMDS encoders through the drm_i2c_encoder_* slave API. The matching
drm/drm_encoder_slave.h is already in drivers/include.

Assisted-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 05:12:27 +03:00
Leency cbd8970197 drivers/include: backport Linux 4.9 bits for amdgpu and nouveau
Test PR / Build (ru_RU) (pull_request) Successful in 3m15s
Test PR / Build (es_ES) (pull_request) Successful in 3m18s
Test PR / Build (en_US) (pull_request) Successful in 3m21s
The headers stay Linux 4.6.x, which the tree's DRM core is built on.
These are small additive backports from Linux 4.9 (4.9.337) needed to
build the amdgpu and nouveau ports.

Modified headers only gain missing struct fields, prototypes and macros.
New headers are minimal stubs, plus a few files taken from Linux 4.9:
kfifo.h, amdgpu_drm.h, nouveau_drm.h, drm_encoder_slave.h,
i2c/ch7006.h, i2c/sil164.h, fence-array.h.

Assisted-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 23:22:08 +03:00
64 changed files with 3183 additions and 5 deletions

No files matched your search

+68
View File
@@ -0,0 +1,68 @@
#ifndef _ACPI_ACPI_H
#define _ACPI_ACPI_H
/*
* Minimal ACPI-CA type surface for KolibriOS.
*
* CONFIG_ACPI is never defined here, so <linux/acpi.h> compiles only its
* "no ACPI" branch - but that branch still mentions a handful of ACPI-CA
* types in the signatures of its inline stubs. Those types are what this
* header provides; there is no ACPI interpreter behind them.
*/
#include <linux/types.h>
typedef u32 acpi_status;
typedef u32 acpi_object_type;
typedef u64 acpi_size;
typedef u64 acpi_io_address;
typedef u64 acpi_physical_address;
typedef void *acpi_handle;
typedef char *acpi_string;
#define AE_OK ((acpi_status) 0x0000)
#define AE_ERROR ((acpi_status) 0x0001)
#define AE_NOT_FOUND ((acpi_status) 0x0005)
#define AE_SUPPORT ((acpi_status) 0x001D)
#define ACPI_SUCCESS(a) ((a) == AE_OK)
#define ACPI_FAILURE(a) ((a) != AE_OK)
#define ACPI_TYPE_INTEGER 0x01
#define ACPI_TYPE_STRING 0x02
#define ACPI_TYPE_BUFFER 0x03
#define ACPI_TYPE_PACKAGE 0x04
#define ACPI_TYPE_ANY 0x00
union acpi_object {
acpi_object_type type;
struct {
acpi_object_type type;
u64 value;
} integer;
struct {
acpi_object_type type;
u32 length;
char *pointer;
} string;
struct {
acpi_object_type type;
u32 length;
u8 *pointer;
} buffer;
struct {
acpi_object_type type;
u32 count;
union acpi_object *elements;
} package;
};
struct acpi_buffer {
acpi_size length;
void *pointer;
};
struct acpi_object_list {
u32 count;
union acpi_object *pointer;
};
#endif /* _ACPI_ACPI_H */
+13
View File
@@ -0,0 +1,13 @@
#ifndef ACPI_BUTTON_H
#define ACPI_BUTTON_H
#include <linux/errno.h>
#include <linux/notifier.h>
/*
* nouveau_connector.c asks the ACPI lid device whether the panel is open
* before trusting an LVDS hotplug. No ACPI here, so report "open" - the same
* answer the upstream !CONFIG_ACPI_BUTTON stub gives.
*/
static inline int acpi_lid_open(void) { return 1; }
static inline int acpi_lid_notifier_register(struct notifier_block *nb) { return -ENODEV; }
static inline int acpi_lid_notifier_unregister(struct notifier_block *nb) { return -ENODEV; }
#endif
+40
View File
@@ -0,0 +1,40 @@
#ifndef _ACPI_PDC_INTEL_H
#define _ACPI_PDC_INTEL_H
/*
* Intel _PDC / _OSC capability bits, included unconditionally by <asm/acpi.h>.
*
* Nothing here evaluates these - KolibriOS drivers never negotiate processor
* capabilities with the firmware - but the definitions have to exist for
* <linux/acpi.h> to be includable at all. Values match the kernel's
* include/acpi/pdc_intel.h.
*/
#define ACPI_PDC_P_FFH (0x0001)
#define ACPI_PDC_C_C1_HALT (0x0002)
#define ACPI_PDC_T_FFH (0x0004)
#define ACPI_PDC_SMP_C1PT (0x0008)
#define ACPI_PDC_SMP_C2C3 (0x0010)
#define ACPI_PDC_SMP_P_SWCOORD (0x0020)
#define ACPI_PDC_SMP_C_SWCOORD (0x0040)
#define ACPI_PDC_SMP_T_SWCOORD (0x0080)
#define ACPI_PDC_C_C1_FFH (0x0100)
#define ACPI_PDC_C_C2C3_FFH (0x0200)
#define ACPI_PDC_SMP_P_HWCOORD (0x0800)
#define ACPI_PDC_EST_CAPABILITY_SMP (ACPI_PDC_SMP_C1PT | \
ACPI_PDC_C_C1_HALT | \
ACPI_PDC_P_FFH)
#define ACPI_PDC_EST_CAPABILITY_SWSMP (ACPI_PDC_SMP_C1PT | \
ACPI_PDC_C_C1_HALT | \
ACPI_PDC_SMP_P_SWCOORD | \
ACPI_PDC_SMP_P_HWCOORD | \
ACPI_PDC_P_FFH)
#define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \
ACPI_PDC_SMP_C1PT | \
ACPI_PDC_C_C1_HALT | \
ACPI_PDC_C_C1_FFH | \
ACPI_PDC_C_C2C3_FFH)
#endif /* _ACPI_PDC_INTEL_H */
+18
View File
@@ -0,0 +1,18 @@
#ifndef __ACPI_VIDEO_H
#define __ACPI_VIDEO_H
/* No ACPI video extensions; nouveau_display.c only calls the register hook. */
#include <linux/errno.h>
enum acpi_backlight_type {
acpi_backlight_undef = -1,
acpi_backlight_none = 0,
acpi_backlight_video,
acpi_backlight_vendor,
acpi_backlight_native,
};
static inline int acpi_video_register(void) { return -ENODEV; }
static inline void acpi_video_unregister(void) { }
static inline enum acpi_backlight_type acpi_video_get_backlight_type(void)
{ return acpi_backlight_vendor; }
#endif
@@ -85,6 +85,9 @@ dma_supported(struct device *dev, u64 mask);
extern int
dma_set_mask(struct device *dev, u64 mask);
extern int
dma_set_coherent_mask(struct device *dev, u64 mask);
extern int
dma_get_cache_alignment(void);
+12
View File
@@ -315,6 +315,18 @@ extern bool xen_biovec_phys_mergeable(const struct bio_vec *vec1,
#define IO_SPACE_LIMIT 0xffff
/*
* Write-combining range management. Upstream declares these under
* CONFIG_MTRR and provides !MTRR fallbacks from <linux/io.h>, which this tree
* does not carry - so they are declared unconditionally here and implemented
* as no-ops by each driver's kos_io.c. arch_io_*_memtype_wc() is the 4.9
* spelling that came in with the PAT rework.
*/
extern int __must_check arch_phys_wc_add(unsigned long base, unsigned long size);
extern void arch_phys_wc_del(int handle);
extern int arch_io_reserve_memtype_wc(resource_size_t start, resource_size_t size);
extern void arch_io_free_memtype_wc(resource_size_t start, resource_size_t size);
#ifdef CONFIG_MTRR
extern int __must_check arch_phys_wc_index(int handle);
#define arch_phys_wc_index arch_phys_wc_index
+30
View File
@@ -359,6 +359,13 @@ struct drm_file {
int event_space;
struct mutex event_read_lock;
/*
* Upstream stores the opening process here. Nothing opens a DRM node
* on this port, so it stays NULL; nouveau_drm.c only feeds it to
* pid_nr() when it names a client.
*/
struct pid *pid;
};
/**
@@ -678,6 +685,14 @@ struct drm_device {
/*@} */
struct list_head filelist;
/*
* Backported from Linux 4.9, which moved filelist from under
* struct_mutex to its own lock. Nothing in the 4.6 core takes it, so
* it only ever serialises the driver against itself.
*/
struct mutex filelist_mutex;
/* Backported from Linux 4.9; unused without a real inode layer. */
struct inode *anon_inode;
/** \name Memory management */
/*@{ */
@@ -748,6 +763,12 @@ struct drm_device {
// struct drm_agp_head *agp; /**< AGP data */
struct pci_dev *pdev; /**< PCI device structure */
/*
* Always NULL here - no platform bus. nouveau_drm.c branches on
* pdev vs platformdev when it builds the device name, and the
* Tegra half of that branch is never taken.
*/
struct platform_device *platformdev;
#ifdef __alpha__
struct pci_controller *hose;
#endif
@@ -981,6 +1002,15 @@ static __inline__ int drm_pci_device_is_agp(struct drm_device *dev)
}
void drm_pci_agp_destroy(struct drm_device *dev);
/*
* Implemented in drm_pci.c and the entry point every port's probe calls, but
* its upstream declaration is in the "#if 0" block below - so each main.c used
* to declare it by hand. Declared here instead.
*/
extern int drm_get_pci_dev(struct pci_dev *pdev,
const struct pci_device_id *ent,
struct drm_driver *driver);
#if 0
extern int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver);
extern void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver);
+27
View File
@@ -152,6 +152,13 @@ struct drm_display_info {
u8 edid_hdmi_dc_modes;
u8 cea_rev;
/*
* Backported from Linux 4.9: maximum TMDS clock in kHz advertised by an
* HDMI sink. drm_edid.c in this tree does not fill it in yet, so it
* stays 0 and drivers fall back to their built-in limit.
*/
int max_tmds_clock;
};
/* data corresponds to displayid vend/prod/serial */
@@ -701,6 +708,17 @@ struct drm_crtc_funcs {
const struct drm_crtc_state *state,
struct drm_property *property,
uint64_t *val);
/*
* Backported from Linux 4.9 for the amdgpu port. The 4.6 DRM core in
* this tree never calls these; they exist so that drivers written
* against the newer struct layout still compile and keep their hooks.
*/
void (*early_unregister)(struct drm_crtc *crtc);
int (*page_flip_target)(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
uint32_t flags, uint32_t target);
};
/**
@@ -1044,6 +1062,9 @@ struct drm_connector_funcs {
const struct drm_connector_state *state,
struct drm_property *property,
uint64_t *val);
/* Backported from Linux 4.9 - see drm_crtc_funcs::early_unregister. */
void (*early_unregister)(struct drm_connector *connector);
};
/**
@@ -1069,6 +1090,9 @@ struct drm_encoder_funcs {
* hotplugged in DRM.
*/
void (*destroy)(struct drm_encoder *encoder);
/* Backported from Linux 4.9 - see drm_crtc_funcs::early_unregister. */
void (*early_unregister)(struct drm_encoder *encoder);
};
#define DRM_CONNECTOR_MAX_ENCODER 3
@@ -1490,6 +1514,9 @@ struct drm_plane_funcs {
const struct drm_plane_state *state,
struct drm_property *property,
uint64_t *val);
/* Backported from Linux 4.9 - see drm_crtc_funcs::early_unregister. */
void (*early_unregister)(struct drm_plane *plane);
};
enum drm_plane_type {
+9
View File
@@ -43,6 +43,15 @@
#include <drm/drm_modeset_helper_vtables.h>
extern void drm_helper_disable_unused_functions(struct drm_device *dev);
/*
* Added after 4.6 and implemented by each port's kos_stubs.c:
* drm_crtc_force_disable_all() is 4.9's unload-time "turn everything off",
* and drm_kms_helper_is_poll_worker() is how 4.9 avoids deadlocking against
* its own hotplug worker - there is no such worker here.
*/
extern void drm_crtc_force_disable_all(struct drm_device *dev);
extern bool drm_kms_helper_is_poll_worker(void);
extern int drm_crtc_helper_set_config(struct drm_mode_set *set);
extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
struct drm_display_mode *mode,
+182
View File
@@ -0,0 +1,182 @@
/*
* 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/drmP.h>
#include <drm/drm_crtc.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)
int drm_i2c_encoder_init(struct drm_device *dev,
struct drm_encoder_slave *encoder,
struct i2c_adapter *adap,
const struct i2c_board_info *info);
/**
* 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 {
struct i2c_driver i2c_driver;
int (*encoder_init)(struct i2c_client *client,
struct drm_device *dev,
struct drm_encoder_slave *encoder);
};
#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)
{
return i2c_register_driver(owner, &driver->i2c_driver);
}
/**
* 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)
{
i2c_del_driver(&driver->i2c_driver);
}
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
+8
View File
@@ -226,6 +226,14 @@ int drm_fb_helper_init(struct drm_device *dev,
struct drm_fb_helper *helper, int crtc_count,
int max_conn);
void drm_fb_helper_fini(struct drm_fb_helper *helper);
/*
* 4.9's fbdev handover. There is no other framebuffer driver to evict on
* KolibriOS; implemented in each port's kos_stubs.c.
*/
struct apertures_struct;
int drm_fb_helper_remove_conflicting_framebuffers(struct apertures_struct *a,
const char *name, bool primary);
int drm_fb_helper_blank(int blank, struct fb_info *info);
int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info);
+10
View File
@@ -0,0 +1,10 @@
#ifndef _DRM_FOURCC_SHIM_H
#define _DRM_FOURCC_SHIM_H
/*
* The tree keeps the format list in uapi/ and the in-kernel helpers in
* drm_crtc.h. Upstream drivers include <drm/drm_fourcc.h>; give them that
* spelling instead of patching every call site. The guard is deliberately
* distinct from the uapi header's own.
*/
#include <uapi/drm/drm_fourcc.h>
#endif
+9
View File
@@ -0,0 +1,9 @@
#ifndef _DRM_MODE_SHIM_H
#define _DRM_MODE_SHIM_H
/*
* Same reason as drm_fourcc.h: upstream drivers spell this <drm/drm_mode.h>
* while the tree keeps it under uapi/. The guard deliberately does not match
* the uapi header's own _DRM_MODE_H, or including this first would suppress it.
*/
#include <uapi/drm/drm_mode.h>
#endif
+86
View File
@@ -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
+63
View File
@@ -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
+9
View File
@@ -257,6 +257,15 @@ struct ttm_buffer_object {
struct reservation_object *resv;
struct reservation_object ttm_resv;
struct mutex wu_mutex;
/*
* Backported from Linux 4.9: fence of the last accelerated move, kept
* outside the reservation object so a pipelined eviction can be waited
* on without blocking other users. The 4.6 TTM in this tree still
* waits synchronously, so the core leaves this NULL; amdgpu sets and
* checks it on its own paths.
*/
struct fence *moving;
};
/**
+12
View File
@@ -434,8 +434,20 @@ struct ttm_bo_driver {
*/
int (*io_mem_reserve)(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem);
void (*io_mem_free)(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem);
/*
* Backported from Linux 4.9 for the amdgpu port. The 4.6 TTM in this
* tree does not consult these hooks - it always uses the default LRU
* placement - but drivers written against 4.9 still populate them.
*/
void (*lru_removal)(struct ttm_buffer_object *bo);
struct list_head *(*lru_tail)(struct ttm_buffer_object *bo);
struct list_head *(*swap_lru_tail)(struct ttm_buffer_object *bo);
};
struct list_head *ttm_bo_default_lru_tail(struct ttm_buffer_object *bo);
struct list_head *ttm_bo_default_swap_lru_tail(struct ttm_buffer_object *bo);
/**
* struct ttm_bo_global_ref - Argument to initialize a struct ttm_bo_global.
*/
+21
View File
@@ -0,0 +1,21 @@
#ifndef _LINUX_CLK_H
#define _LINUX_CLK_H
/*
* Tegra-only. nvif/os.h pulls this in unconditionally, but the only nouveau
* code that calls a clk_* helper is nvkm/engine/device/tegra.c, which this
* port does not build.
*/
#include <linux/errno.h>
#include <linux/err.h>
struct clk;
struct device;
static inline struct clk *clk_get(struct device *dev, const char *id)
{ return ERR_PTR(-ENOENT); }
static inline void clk_put(struct clk *clk) { }
static inline int clk_prepare_enable(struct clk *clk) { return -ENOSYS; }
static inline void clk_disable_unprepare(struct clk *clk) { }
static inline unsigned long clk_get_rate(struct clk *clk) { return 0; }
static inline int clk_set_rate(struct clk *clk, unsigned long rate) { return -ENOSYS; }
#endif
+14
View File
@@ -0,0 +1,14 @@
#ifndef _LINUX_CONSOLE_H
#define _LINUX_CONSOLE_H
/* KolibriOS has no VT console layer; the fbdev handover hooks are no-ops. */
#define CON_PRINTBUFFER (1)
#define CON_CONSDEV (2)
#define CON_ENABLED (4)
#define CON_BOOT (8)
#define CON_ANYTIME (16)
#define CON_BRL (32)
static inline void console_lock(void) { }
static inline void console_unlock(void) { }
static inline int console_trylock(void) { return 1; }
#endif
+7
View File
@@ -0,0 +1,7 @@
#ifndef _LINUX_DEBUGFS_H
#define _LINUX_DEBUGFS_H
/* No debugfs in KolibriOS - CONFIG_DEBUG_FS is never defined. */
#include <linux/types.h>
struct dentry;
struct file_operations;
#endif
+29
View File
@@ -31,6 +31,12 @@ enum probe_type {
struct device_driver {
const char *name;
/*
* Restored for drm_encoder_slave.c, which pins the slave encoder's
* module around a bind. Nothing is ever bound on this port, so it
* stays NULL and try_module_get()/module_put() are no-ops.
*/
struct module *owner;
const char *mod_name; /* used for built-in modules */
bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
@@ -126,5 +132,28 @@ static inline __printf(2, 3)
void dev_notice(const struct device *dev, const char *fmt, ...)
{}
/*
* sysfs attribute types. KolibriOS has no sysfs, so nothing ever walks these
* tables - but drivers still declare them at file scope, so the layout has to
* exist. Matches the upstream definitions field for field.
*/
#include <linux/sysfs.h>
struct device_attribute {
struct attribute attr;
ssize_t (*show)(struct device *dev, struct device_attribute *attr,
char *buf);
ssize_t (*store)(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count);
};
#define __ATTR(_name, _mode, _show, _store) { \
.attr = { .name = __stringify(_name), .mode = (_mode) }, \
.show = _show, \
.store = _store, \
}
#define DEVICE_ATTR(_name, _mode, _show, _store) \
struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
#endif /* _DEVICE_H_ */
+6
View File
@@ -131,6 +131,12 @@ struct dma_buf {
const char *exp_name;
struct list_head list_node;
void *priv;
/*
* Upstream keeps the exporter's reservation object here. No dma-buf
* is ever created on this port, so nouveau_prime.c's import path is
* dead code - but it dereferences the field, so it has to exist.
*/
struct reservation_object *resv;
};
/**
+7
View File
@@ -0,0 +1,7 @@
#ifndef _LINUX_EFI_H
#define _LINUX_EFI_H
/* KolibriOS boots via BIOS only; amdgpu only tests efi_enabled(). */
#define EFI_BOOT 0
#define EFI_RUNTIME_SERVICES 1
static inline bool efi_enabled(int feature) { return false; }
#endif
+6 -1
View File
@@ -470,7 +470,12 @@ struct fb_info {
struct fb_fix_screeninfo fix; /* Current fix */
struct fb_monspecs monspecs; /* Current Monitor specs */
// struct work_struct queue; /* Framebuffer event queue */
// struct fb_pixmap pixmap; /* Image hardware mapper */
/*
* Restored for nouveau, which sets pixmap.buf_align after
* drm_fb_helper_initial_config(). Nothing on this port consumes the
* field - there is no fbcon - but the assignment has to compile.
*/
struct fb_pixmap pixmap; /* Image hardware mapper */
// struct fb_pixmap sprite; /* Cursor hardware mapper */
// struct fb_cmap cmap; /* Current cmap */
struct list_head modelist; /* mode list */
+83
View File
@@ -0,0 +1,83 @@
/*
* fence-array: aggregates fence to be waited together
*
* Copyright (C) 2016 Collabora Ltd
* Copyright (C) 2016 Advanced Micro Devices, Inc.
* Authors:
* Gustavo Padovan <gustavo@padovan.org>
* Christian König <christian.koenig@amd.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#ifndef __LINUX_FENCE_ARRAY_H
#define __LINUX_FENCE_ARRAY_H
#include <linux/fence.h>
/**
* struct fence_array_cb - callback helper for fence array
* @cb: fence callback structure for signaling
* @array: reference to the parent fence array object
*/
struct fence_array_cb {
struct fence_cb cb;
struct fence_array *array;
};
/**
* struct fence_array - fence to represent an array of fences
* @base: fence base class
* @lock: spinlock for fence handling
* @num_fences: number of fences in the array
* @num_pending: fences in the array still pending
* @fences: array of the fences
*/
struct fence_array {
struct fence base;
spinlock_t lock;
unsigned num_fences;
atomic_t num_pending;
struct fence **fences;
};
extern const struct fence_ops fence_array_ops;
/**
* fence_is_array - check if a fence is from the array subsclass
*
* Return true if it is a fence_array and false otherwise.
*/
static inline bool fence_is_array(struct fence *fence)
{
return fence->ops == &fence_array_ops;
}
/**
* to_fence_array - cast a fence to a fence_array
* @fence: fence to cast to a fence_array
*
* Returns NULL if the fence is not a fence_array,
* or the fence_array otherwise.
*/
static inline struct fence_array *to_fence_array(struct fence *fence)
{
if (fence->ops != &fence_array_ops)
return NULL;
return container_of(fence, struct fence_array, base);
}
struct fence_array *fence_array_create(int num_fences, struct fence **fences,
u64 context, unsigned seqno,
bool signal_on_any);
#endif /* __LINUX_FENCE_ARRAY_H */
+35
View File
@@ -0,0 +1,35 @@
#ifndef _LINUX_HRTIMER_H
#define _LINUX_HRTIMER_H
/*
* amdgpu_mode.h only embeds a struct hrtimer in the virtual-DCE crtc and never
* arms it on this port, so a structural stub is enough.
*/
#include <linux/types.h>
#include <linux/ktime.h>
enum hrtimer_restart { HRTIMER_NORESTART, HRTIMER_RESTART };
enum hrtimer_mode {
HRTIMER_MODE_ABS = 0x0,
HRTIMER_MODE_REL = 0x1,
HRTIMER_MODE_PINNED = 0x2,
};
enum hrtimer_base_type { HRTIMER_BASE_MONOTONIC, HRTIMER_MAX_CLOCK_BASES };
struct hrtimer {
ktime_t _softexpires;
enum hrtimer_restart (*function)(struct hrtimer *);
int state;
};
static inline void hrtimer_init(struct hrtimer *timer, int which, enum hrtimer_mode mode)
{ timer->function = NULL; timer->state = 0; }
static inline int hrtimer_start(struct hrtimer *t, ktime_t tim, enum hrtimer_mode m) { return 0; }
static inline int hrtimer_cancel(struct hrtimer *t) { return 0; }
static inline int hrtimer_try_to_cancel(struct hrtimer *t) { return 0; }
static inline bool hrtimer_active(const struct hrtimer *t) { return false; }
static inline void hrtimer_start_range_ns(struct hrtimer *t, ktime_t tim,
u64 range_ns, enum hrtimer_mode m) { }
/* Sleeps through the DDK's delay(); see the driver's kos_* glue. */
extern int schedule_hrtimeout(ktime_t *expires, const enum hrtimer_mode mode);
#endif
+27
View File
@@ -0,0 +1,27 @@
#ifndef _LINUX_HWMON_SYSFS_H
#define _LINUX_HWMON_SYSFS_H
/* sysfs is absent; amdgpu_pm.c's hwmon attributes are compiled out to stubs. */
#include <linux/device.h>
struct sensor_device_attribute {
struct device_attribute dev_attr;
int index;
};
#define to_sensor_dev_attr(_dev_attr) \
container_of(_dev_attr, struct sensor_device_attribute, dev_attr)
#define SENSOR_ATTR(_name, _mode, _show, _store, _index) \
{ .dev_attr = __ATTR(_name, _mode, _show, _store), .index = _index }
#define SENSOR_DEVICE_ATTR(_name, _mode, _show, _store, _index) \
struct sensor_device_attribute sensor_dev_attr_##_name = \
SENSOR_ATTR(_name, _mode, _show, _store, _index)
struct sensor_device_attribute_2 {
struct device_attribute dev_attr;
u8 index;
u8 nr;
};
#define to_sensor_dev_attr_2(_dev_attr) \
container_of(_dev_attr, struct sensor_device_attribute_2, dev_attr)
#endif
+22 -2
View File
@@ -52,6 +52,19 @@ struct i2c_board_info;
extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
int num);
/*
* Declared here rather than left implicit: i2c-core.c defines them, and
* nouveau reaches all three - i2c_new_device()/i2c_unregister_device() from
* nvkm/subdev/therm/ic.c, i2c_register_driver() through the i2c_add_driver()
* inline below.
*/
struct module;
extern int i2c_register_driver(struct module *owner, struct i2c_driver *driver);
extern void i2c_del_driver(struct i2c_driver *driver);
extern struct i2c_client *i2c_new_device(struct i2c_adapter *adap,
struct i2c_board_info const *info);
extern void i2c_unregister_device(struct i2c_client *client);
/**
* struct i2c_driver - represent an I2C device driver
* @class: What kind of i2c device we instantiate (for detect)
@@ -114,11 +127,18 @@ struct i2c_driver {
*/
int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
// struct device_driver driver;
/*
* Restored for nouveau: nvkm/subdev/therm/ic.c reaches the bound
* driver through to_i2c_driver(client->dev.driver)->detect(). There
* is no driver-model binding on this port, so dev.driver is always
* NULL and the probe short-circuits - but the fields have to exist
* for to_i2c_driver() to compile.
*/
struct device_driver driver;
const struct i2c_device_id *id_table;
/* Device detection callback for automatic device creation */
// int (*detect)(struct i2c_client *, struct i2c_board_info *);
int (*detect)(struct i2c_client *, struct i2c_board_info *);
const unsigned short *address_list;
struct list_head clients;
};
+12
View File
@@ -5,6 +5,18 @@
#include <linux/kernel.h>
#include <linux/bitops.h>
#include <linux/irqreturn.h>
/*
* Taking an interrupt outside drm_irq_install(). nouveau's nvkm_pci_init()
* does exactly that, so the driver supplies request_irq()/free_irq() over
* AttachIntHandler(); the signatures are upstream's.
*/
typedef irqreturn_t (*irq_handler_t)(int irq, void *dev_id);
extern int request_irq(unsigned int irq, irq_handler_t handler,
unsigned long flags, const char *name, void *dev_id);
extern void free_irq(unsigned int irq, void *dev_id);
#include <linux/kref.h>
#include <linux/atomic.h>
/*
+37
View File
@@ -0,0 +1,37 @@
#ifndef _LINUX_IOMMU_H
#define _LINUX_IOMMU_H
/*
* No IOMMU on this port. nvif/os.h includes it unconditionally; the only user
* is the Tegra SMMU path in nvkm/engine/device/tegra.c, which is not built.
*/
#include <linux/errno.h>
#include <linux/types.h>
#define IOMMU_READ (1 << 0)
#define IOMMU_WRITE (1 << 1)
#define IOMMU_CACHE (1 << 2)
struct device;
struct iommu_domain;
struct iommu_group;
struct iommu_domain_geometry {
dma_addr_t aperture_start;
dma_addr_t aperture_end;
bool force_aperture;
};
static inline struct iommu_domain *iommu_domain_alloc(void *bus) { return NULL; }
static inline void iommu_domain_free(struct iommu_domain *d) { }
static inline int iommu_attach_device(struct iommu_domain *d, struct device *dev)
{ return -ENODEV; }
static inline void iommu_detach_device(struct iommu_domain *d, struct device *dev) { }
static inline struct iommu_group *iommu_group_get(struct device *dev) { return NULL; }
static inline int iommu_map(struct iommu_domain *domain, unsigned long iova,
phys_addr_t paddr, size_t size, int prot)
{ return -ENODEV; }
static inline size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova,
size_t size)
{ return 0; }
static inline void iommu_group_put(struct iommu_group *g) { }
#endif
+27
View File
@@ -0,0 +1,27 @@
#ifndef _LINUX_IRQ_H
#define _LINUX_IRQ_H
/*
* KolibriOS has no irq_domain layer. amdgpu_irq.c is patched to dispatch IH
* ring entries straight to the registered amdgpu_irq_src, so only the types it
* still mentions need to exist.
*/
#include <linux/types.h>
struct irq_data {
unsigned int irq;
unsigned long hwirq;
void *chip_data;
};
struct irq_chip {
const char *name;
void (*irq_mask)(struct irq_data *data);
void (*irq_unmask)(struct irq_data *data);
};
static inline void *irq_data_get_irq_chip_data(struct irq_data *d)
{
return d ? d->chip_data : NULL;
}
static inline void handle_simple_irq(void) { }
#endif
+41
View File
@@ -0,0 +1,41 @@
#ifndef _LINUX_IRQDOMAIN_H
#define _LINUX_IRQDOMAIN_H
/*
* KolibriOS has no irq domain layer.
*
* amdgpu builds a linear domain purely so that a *different* driver (the ACP
* audio co-processor) can receive GPU interrupts by Linux irq number. ACP is
* not part of this port, so no mapping is ever created: adev->irq.virq[] stays
* zero and amdgpu_irq_dispatch() always takes its direct-call branch.
*
* These declarations therefore exist to keep the domain setup compiling and
* succeeding; the implementations in the driver's kos_stubs.c do nothing.
*/
#include <linux/types.h>
#include <linux/irq.h>
typedef unsigned long irq_hw_number_t;
struct irq_domain;
struct device_node;
struct irq_domain_ops {
int (*map)(struct irq_domain *d, unsigned int virq, irq_hw_number_t hw);
void (*unmap)(struct irq_domain *d, unsigned int virq);
int (*xlate)(struct irq_domain *d, struct device_node *node,
const u32 *intspec, unsigned int intsize,
unsigned long *out_hwirq, unsigned int *out_type);
};
struct irq_domain *irq_domain_add_linear(struct device_node *of_node,
unsigned int size,
const struct irq_domain_ops *ops,
void *host_data);
void irq_domain_remove(struct irq_domain *domain);
unsigned int irq_create_mapping(struct irq_domain *domain, irq_hw_number_t hwirq);
unsigned int irq_find_mapping(struct irq_domain *domain, irq_hw_number_t hwirq);
int generic_handle_irq(unsigned int irq);
void irq_set_chip_and_handler(unsigned int irq, struct irq_chip *chip,
void (*handle)(void));
#endif /* _LINUX_IRQDOMAIN_H */
+33 -1
View File
@@ -684,7 +684,20 @@ typedef union
u64 raw;
}evhandle_t;
struct vm_area_struct {};
/*
* KolibriOS has no user address space that drivers can map into, so these are
* placeholders. The fields exist because the mmap/userptr entry points of the
* ported DRM drivers reference them; those paths are never reached, since no
* ioctl surface is exposed to user code.
*/
struct vm_area_struct {
unsigned long vm_start;
unsigned long vm_end;
unsigned long vm_pgoff;
unsigned long vm_flags;
struct file *vm_file;
void *vm_private_data;
};
struct address_space {};
#define in_dbg_master() (0)
@@ -731,6 +744,13 @@ int del_timer(struct timer_list *timer);
#define mmiowb() barrier()
/* String-to-integer conversions; each driver's kos_kernel.c implements them. */
extern int kstrtol(const char *s, unsigned int base, long *res);
extern int kstrtoul(const char *s, unsigned int base, unsigned long *res);
extern int kstrtoint(const char *s, unsigned int base, int *res);
extern int kstrtou32(const char *s, unsigned int base, u32 *res);
#define dev_err(dev, format, arg...) \
printk("Error %s " format, __func__ , ## arg)
@@ -740,6 +760,18 @@ int del_timer(struct timer_list *timer);
#define dev_info(dev, format, arg...) \
printk("Info %s " format , __func__, ## arg)
/*
* nouveau routes all of its logging through dev_*() (NV_PRINTK in
* nouveau_drv.h picks the level by name), so the two levels the other drivers
* never needed have to exist as well. dev_dbg() keeps its arguments checked
* but emits nothing, matching the !CONFIG_DYNAMIC_DEBUG behaviour upstream.
*/
#define dev_crit(dev, format, arg...) \
printk("Critical %s " format, __func__ , ## arg)
#define dev_dbg(dev, format, arg...) \
do { if (0) printk(format, ## arg); } while (0)
struct page
{
unsigned int addr;
+833
View File
@@ -0,0 +1,833 @@
/*
* A generic kernel FIFO implementation
*
* Copyright (C) 2013 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef _LINUX_KFIFO_H
#define _LINUX_KFIFO_H
/*
* How to porting drivers to the new generic FIFO API:
*
* - Modify the declaration of the "struct kfifo *" object into a
* in-place "struct kfifo" object
* - Init the in-place object with kfifo_alloc() or kfifo_init()
* Note: The address of the in-place "struct kfifo" object must be
* passed as the first argument to this functions
* - Replace the use of __kfifo_put into kfifo_in and __kfifo_get
* into kfifo_out
* - Replace the use of kfifo_put into kfifo_in_spinlocked and kfifo_get
* into kfifo_out_spinlocked
* Note: the spinlock pointer formerly passed to kfifo_init/kfifo_alloc
* must be passed now to the kfifo_in_spinlocked and kfifo_out_spinlocked
* as the last parameter
* - The formerly __kfifo_* functions are renamed into kfifo_*
*/
/*
* Note about locking : There is no locking required until only * one reader
* and one writer is using the fifo and no kfifo_reset() will be * called
* kfifo_reset_out() can be safely used, until it will be only called
* in the reader thread.
* For multiple writer and one reader there is only a need to lock the writer.
* And vice versa for only one writer and multiple reader there is only a need
* to lock the reader.
*/
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/stddef.h>
#include <linux/scatterlist.h>
struct __kfifo {
unsigned int in;
unsigned int out;
unsigned int mask;
unsigned int esize;
void *data;
};
#define __STRUCT_KFIFO_COMMON(datatype, recsize, ptrtype) \
union { \
struct __kfifo kfifo; \
datatype *type; \
const datatype *const_type; \
char (*rectype)[recsize]; \
ptrtype *ptr; \
ptrtype const *ptr_const; \
}
#define __STRUCT_KFIFO(type, size, recsize, ptrtype) \
{ \
__STRUCT_KFIFO_COMMON(type, recsize, ptrtype); \
type buf[((size < 2) || (size & (size - 1))) ? -1 : size]; \
}
#define STRUCT_KFIFO(type, size) \
struct __STRUCT_KFIFO(type, size, 0, type)
#define __STRUCT_KFIFO_PTR(type, recsize, ptrtype) \
{ \
__STRUCT_KFIFO_COMMON(type, recsize, ptrtype); \
type buf[0]; \
}
#define STRUCT_KFIFO_PTR(type) \
struct __STRUCT_KFIFO_PTR(type, 0, type)
/*
* define compatibility "struct kfifo" for dynamic allocated fifos
*/
struct kfifo __STRUCT_KFIFO_PTR(unsigned char, 0, void);
#define STRUCT_KFIFO_REC_1(size) \
struct __STRUCT_KFIFO(unsigned char, size, 1, void)
#define STRUCT_KFIFO_REC_2(size) \
struct __STRUCT_KFIFO(unsigned char, size, 2, void)
/*
* define kfifo_rec types
*/
struct kfifo_rec_ptr_1 __STRUCT_KFIFO_PTR(unsigned char, 1, void);
struct kfifo_rec_ptr_2 __STRUCT_KFIFO_PTR(unsigned char, 2, void);
/*
* helper macro to distinguish between real in place fifo where the fifo
* array is a part of the structure and the fifo type where the array is
* outside of the fifo structure.
*/
#define __is_kfifo_ptr(fifo) (sizeof(*fifo) == sizeof(struct __kfifo))
/**
* DECLARE_KFIFO_PTR - macro to declare a fifo pointer object
* @fifo: name of the declared fifo
* @type: type of the fifo elements
*/
#define DECLARE_KFIFO_PTR(fifo, type) STRUCT_KFIFO_PTR(type) fifo
/**
* DECLARE_KFIFO - macro to declare a fifo object
* @fifo: name of the declared fifo
* @type: type of the fifo elements
* @size: the number of elements in the fifo, this must be a power of 2
*/
#define DECLARE_KFIFO(fifo, type, size) STRUCT_KFIFO(type, size) fifo
/**
* INIT_KFIFO - Initialize a fifo declared by DECLARE_KFIFO
* @fifo: name of the declared fifo datatype
*/
#define INIT_KFIFO(fifo) \
(void)({ \
typeof(&(fifo)) __tmp = &(fifo); \
struct __kfifo *__kfifo = &__tmp->kfifo; \
__kfifo->in = 0; \
__kfifo->out = 0; \
__kfifo->mask = __is_kfifo_ptr(__tmp) ? 0 : ARRAY_SIZE(__tmp->buf) - 1;\
__kfifo->esize = sizeof(*__tmp->buf); \
__kfifo->data = __is_kfifo_ptr(__tmp) ? NULL : __tmp->buf; \
})
/**
* DEFINE_KFIFO - macro to define and initialize a fifo
* @fifo: name of the declared fifo datatype
* @type: type of the fifo elements
* @size: the number of elements in the fifo, this must be a power of 2
*
* Note: the macro can be used for global and local fifo data type variables.
*/
#define DEFINE_KFIFO(fifo, type, size) \
DECLARE_KFIFO(fifo, type, size) = \
(typeof(fifo)) { \
{ \
{ \
.in = 0, \
.out = 0, \
.mask = __is_kfifo_ptr(&(fifo)) ? \
0 : \
ARRAY_SIZE((fifo).buf) - 1, \
.esize = sizeof(*(fifo).buf), \
.data = __is_kfifo_ptr(&(fifo)) ? \
NULL : \
(fifo).buf, \
} \
} \
}
static inline unsigned int __must_check
__kfifo_uint_must_check_helper(unsigned int val)
{
return val;
}
static inline int __must_check
__kfifo_int_must_check_helper(int val)
{
return val;
}
/**
* kfifo_initialized - Check if the fifo is initialized
* @fifo: address of the fifo to check
*
* Return %true if fifo is initialized, otherwise %false.
* Assumes the fifo was 0 before.
*/
#define kfifo_initialized(fifo) ((fifo)->kfifo.mask)
/**
* kfifo_esize - returns the size of the element managed by the fifo
* @fifo: address of the fifo to be used
*/
#define kfifo_esize(fifo) ((fifo)->kfifo.esize)
/**
* kfifo_recsize - returns the size of the record length field
* @fifo: address of the fifo to be used
*/
#define kfifo_recsize(fifo) (sizeof(*(fifo)->rectype))
/**
* kfifo_size - returns the size of the fifo in elements
* @fifo: address of the fifo to be used
*/
#define kfifo_size(fifo) ((fifo)->kfifo.mask + 1)
/**
* kfifo_reset - removes the entire fifo content
* @fifo: address of the fifo to be used
*
* Note: usage of kfifo_reset() is dangerous. It should be only called when the
* fifo is exclusived locked or when it is secured that no other thread is
* accessing the fifo.
*/
#define kfifo_reset(fifo) \
(void)({ \
typeof((fifo) + 1) __tmp = (fifo); \
__tmp->kfifo.in = __tmp->kfifo.out = 0; \
})
/**
* kfifo_reset_out - skip fifo content
* @fifo: address of the fifo to be used
*
* Note: The usage of kfifo_reset_out() is safe until it will be only called
* from the reader thread and there is only one concurrent reader. Otherwise
* it is dangerous and must be handled in the same way as kfifo_reset().
*/
#define kfifo_reset_out(fifo) \
(void)({ \
typeof((fifo) + 1) __tmp = (fifo); \
__tmp->kfifo.out = __tmp->kfifo.in; \
})
/**
* kfifo_len - returns the number of used elements in the fifo
* @fifo: address of the fifo to be used
*/
#define kfifo_len(fifo) \
({ \
typeof((fifo) + 1) __tmpl = (fifo); \
__tmpl->kfifo.in - __tmpl->kfifo.out; \
})
/**
* kfifo_is_empty - returns true if the fifo is empty
* @fifo: address of the fifo to be used
*/
#define kfifo_is_empty(fifo) \
({ \
typeof((fifo) + 1) __tmpq = (fifo); \
__tmpq->kfifo.in == __tmpq->kfifo.out; \
})
/**
* kfifo_is_full - returns true if the fifo is full
* @fifo: address of the fifo to be used
*/
#define kfifo_is_full(fifo) \
({ \
typeof((fifo) + 1) __tmpq = (fifo); \
kfifo_len(__tmpq) > __tmpq->kfifo.mask; \
})
/**
* kfifo_avail - returns the number of unused elements in the fifo
* @fifo: address of the fifo to be used
*/
#define kfifo_avail(fifo) \
__kfifo_uint_must_check_helper( \
({ \
typeof((fifo) + 1) __tmpq = (fifo); \
const size_t __recsize = sizeof(*__tmpq->rectype); \
unsigned int __avail = kfifo_size(__tmpq) - kfifo_len(__tmpq); \
(__recsize) ? ((__avail <= __recsize) ? 0 : \
__kfifo_max_r(__avail - __recsize, __recsize)) : \
__avail; \
}) \
)
/**
* kfifo_skip - skip output data
* @fifo: address of the fifo to be used
*/
#define kfifo_skip(fifo) \
(void)({ \
typeof((fifo) + 1) __tmp = (fifo); \
const size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \
if (__recsize) \
__kfifo_skip_r(__kfifo, __recsize); \
else \
__kfifo->out++; \
})
/**
* kfifo_peek_len - gets the size of the next fifo record
* @fifo: address of the fifo to be used
*
* This function returns the size of the next fifo record in number of bytes.
*/
#define kfifo_peek_len(fifo) \
__kfifo_uint_must_check_helper( \
({ \
typeof((fifo) + 1) __tmp = (fifo); \
const size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \
(!__recsize) ? kfifo_len(__tmp) * sizeof(*__tmp->type) : \
__kfifo_len_r(__kfifo, __recsize); \
}) \
)
/**
* kfifo_alloc - dynamically allocates a new fifo buffer
* @fifo: pointer to the fifo
* @size: the number of elements in the fifo, this must be a power of 2
* @gfp_mask: get_free_pages mask, passed to kmalloc()
*
* This macro dynamically allocates a new fifo buffer.
*
* The numer of elements will be rounded-up to a power of 2.
* The fifo will be release with kfifo_free().
* Return 0 if no error, otherwise an error code.
*/
#define kfifo_alloc(fifo, size, gfp_mask) \
__kfifo_int_must_check_helper( \
({ \
typeof((fifo) + 1) __tmp = (fifo); \
struct __kfifo *__kfifo = &__tmp->kfifo; \
__is_kfifo_ptr(__tmp) ? \
__kfifo_alloc(__kfifo, size, sizeof(*__tmp->type), gfp_mask) : \
-EINVAL; \
}) \
)
/**
* kfifo_free - frees the fifo
* @fifo: the fifo to be freed
*/
#define kfifo_free(fifo) \
({ \
typeof((fifo) + 1) __tmp = (fifo); \
struct __kfifo *__kfifo = &__tmp->kfifo; \
if (__is_kfifo_ptr(__tmp)) \
__kfifo_free(__kfifo); \
})
/**
* kfifo_init - initialize a fifo using a preallocated buffer
* @fifo: the fifo to assign the buffer
* @buffer: the preallocated buffer to be used
* @size: the size of the internal buffer, this have to be a power of 2
*
* This macro initialize a fifo using a preallocated buffer.
*
* The numer of elements will be rounded-up to a power of 2.
* Return 0 if no error, otherwise an error code.
*/
#define kfifo_init(fifo, buffer, size) \
({ \
typeof((fifo) + 1) __tmp = (fifo); \
struct __kfifo *__kfifo = &__tmp->kfifo; \
__is_kfifo_ptr(__tmp) ? \
__kfifo_init(__kfifo, buffer, size, sizeof(*__tmp->type)) : \
-EINVAL; \
})
/**
* kfifo_put - put data into the fifo
* @fifo: address of the fifo to be used
* @val: the data to be added
*
* This macro copies the given value into the fifo.
* It returns 0 if the fifo was full. Otherwise it returns the number
* processed elements.
*
* Note that with only one concurrent reader and one concurrent
* writer, you don't need extra locking to use these macro.
*/
#define kfifo_put(fifo, val) \
({ \
typeof((fifo) + 1) __tmp = (fifo); \
typeof(*__tmp->const_type) __val = (val); \
unsigned int __ret; \
size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \
if (__recsize) \
__ret = __kfifo_in_r(__kfifo, &__val, sizeof(__val), \
__recsize); \
else { \
__ret = !kfifo_is_full(__tmp); \
if (__ret) { \
(__is_kfifo_ptr(__tmp) ? \
((typeof(__tmp->type))__kfifo->data) : \
(__tmp->buf) \
)[__kfifo->in & __tmp->kfifo.mask] = \
*(typeof(__tmp->type))&__val; \
smp_wmb(); \
__kfifo->in++; \
} \
} \
__ret; \
})
/**
* kfifo_get - get data from the fifo
* @fifo: address of the fifo to be used
* @val: address where to store the data
*
* This macro reads the data from the fifo.
* It returns 0 if the fifo was empty. Otherwise it returns the number
* processed elements.
*
* Note that with only one concurrent reader and one concurrent
* writer, you don't need extra locking to use these macro.
*/
#define kfifo_get(fifo, val) \
__kfifo_uint_must_check_helper( \
({ \
typeof((fifo) + 1) __tmp = (fifo); \
typeof(__tmp->ptr) __val = (val); \
unsigned int __ret; \
const size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \
if (__recsize) \
__ret = __kfifo_out_r(__kfifo, __val, sizeof(*__val), \
__recsize); \
else { \
__ret = !kfifo_is_empty(__tmp); \
if (__ret) { \
*(typeof(__tmp->type))__val = \
(__is_kfifo_ptr(__tmp) ? \
((typeof(__tmp->type))__kfifo->data) : \
(__tmp->buf) \
)[__kfifo->out & __tmp->kfifo.mask]; \
smp_wmb(); \
__kfifo->out++; \
} \
} \
__ret; \
}) \
)
/**
* kfifo_peek - get data from the fifo without removing
* @fifo: address of the fifo to be used
* @val: address where to store the data
*
* This reads the data from the fifo without removing it from the fifo.
* It returns 0 if the fifo was empty. Otherwise it returns the number
* processed elements.
*
* Note that with only one concurrent reader and one concurrent
* writer, you don't need extra locking to use these macro.
*/
#define kfifo_peek(fifo, val) \
__kfifo_uint_must_check_helper( \
({ \
typeof((fifo) + 1) __tmp = (fifo); \
typeof(__tmp->ptr) __val = (val); \
unsigned int __ret; \
const size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \
if (__recsize) \
__ret = __kfifo_out_peek_r(__kfifo, __val, sizeof(*__val), \
__recsize); \
else { \
__ret = !kfifo_is_empty(__tmp); \
if (__ret) { \
*(typeof(__tmp->type))__val = \
(__is_kfifo_ptr(__tmp) ? \
((typeof(__tmp->type))__kfifo->data) : \
(__tmp->buf) \
)[__kfifo->out & __tmp->kfifo.mask]; \
smp_wmb(); \
} \
} \
__ret; \
}) \
)
/**
* kfifo_in - put data into the fifo
* @fifo: address of the fifo to be used
* @buf: the data to be added
* @n: number of elements to be added
*
* This macro copies the given buffer into the fifo and returns the
* number of copied elements.
*
* Note that with only one concurrent reader and one concurrent
* writer, you don't need extra locking to use these macro.
*/
#define kfifo_in(fifo, buf, n) \
({ \
typeof((fifo) + 1) __tmp = (fifo); \
typeof(__tmp->ptr_const) __buf = (buf); \
unsigned long __n = (n); \
const size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \
(__recsize) ?\
__kfifo_in_r(__kfifo, __buf, __n, __recsize) : \
__kfifo_in(__kfifo, __buf, __n); \
})
/**
* kfifo_in_spinlocked - put data into the fifo using a spinlock for locking
* @fifo: address of the fifo to be used
* @buf: the data to be added
* @n: number of elements to be added
* @lock: pointer to the spinlock to use for locking
*
* This macro copies the given values buffer into the fifo and returns the
* number of copied elements.
*/
#define kfifo_in_spinlocked(fifo, buf, n, lock) \
({ \
unsigned long __flags; \
unsigned int __ret; \
spin_lock_irqsave(lock, __flags); \
__ret = kfifo_in(fifo, buf, n); \
spin_unlock_irqrestore(lock, __flags); \
__ret; \
})
/* alias for kfifo_in_spinlocked, will be removed in a future release */
#define kfifo_in_locked(fifo, buf, n, lock) \
kfifo_in_spinlocked(fifo, buf, n, lock)
/**
* kfifo_out - get data from the fifo
* @fifo: address of the fifo to be used
* @buf: pointer to the storage buffer
* @n: max. number of elements to get
*
* This macro get some data from the fifo and return the numbers of elements
* copied.
*
* Note that with only one concurrent reader and one concurrent
* writer, you don't need extra locking to use these macro.
*/
#define kfifo_out(fifo, buf, n) \
__kfifo_uint_must_check_helper( \
({ \
typeof((fifo) + 1) __tmp = (fifo); \
typeof(__tmp->ptr) __buf = (buf); \
unsigned long __n = (n); \
const size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \
(__recsize) ?\
__kfifo_out_r(__kfifo, __buf, __n, __recsize) : \
__kfifo_out(__kfifo, __buf, __n); \
}) \
)
/**
* kfifo_out_spinlocked - get data from the fifo using a spinlock for locking
* @fifo: address of the fifo to be used
* @buf: pointer to the storage buffer
* @n: max. number of elements to get
* @lock: pointer to the spinlock to use for locking
*
* This macro get the data from the fifo and return the numbers of elements
* copied.
*/
#define kfifo_out_spinlocked(fifo, buf, n, lock) \
__kfifo_uint_must_check_helper( \
({ \
unsigned long __flags; \
unsigned int __ret; \
spin_lock_irqsave(lock, __flags); \
__ret = kfifo_out(fifo, buf, n); \
spin_unlock_irqrestore(lock, __flags); \
__ret; \
}) \
)
/* alias for kfifo_out_spinlocked, will be removed in a future release */
#define kfifo_out_locked(fifo, buf, n, lock) \
kfifo_out_spinlocked(fifo, buf, n, lock)
/**
* kfifo_from_user - puts some data from user space into the fifo
* @fifo: address of the fifo to be used
* @from: pointer to the data to be added
* @len: the length of the data to be added
* @copied: pointer to output variable to store the number of copied bytes
*
* This macro copies at most @len bytes from the @from into the
* fifo, depending of the available space and returns -EFAULT/0.
*
* Note that with only one concurrent reader and one concurrent
* writer, you don't need extra locking to use these macro.
*/
#define kfifo_from_user(fifo, from, len, copied) \
__kfifo_uint_must_check_helper( \
({ \
typeof((fifo) + 1) __tmp = (fifo); \
const void __user *__from = (from); \
unsigned int __len = (len); \
unsigned int *__copied = (copied); \
const size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \
(__recsize) ? \
__kfifo_from_user_r(__kfifo, __from, __len, __copied, __recsize) : \
__kfifo_from_user(__kfifo, __from, __len, __copied); \
}) \
)
/**
* kfifo_to_user - copies data from the fifo into user space
* @fifo: address of the fifo to be used
* @to: where the data must be copied
* @len: the size of the destination buffer
* @copied: pointer to output variable to store the number of copied bytes
*
* This macro copies at most @len bytes from the fifo into the
* @to buffer and returns -EFAULT/0.
*
* Note that with only one concurrent reader and one concurrent
* writer, you don't need extra locking to use these macro.
*/
#define kfifo_to_user(fifo, to, len, copied) \
__kfifo_uint_must_check_helper( \
({ \
typeof((fifo) + 1) __tmp = (fifo); \
void __user *__to = (to); \
unsigned int __len = (len); \
unsigned int *__copied = (copied); \
const size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \
(__recsize) ? \
__kfifo_to_user_r(__kfifo, __to, __len, __copied, __recsize) : \
__kfifo_to_user(__kfifo, __to, __len, __copied); \
}) \
)
/**
* kfifo_dma_in_prepare - setup a scatterlist for DMA input
* @fifo: address of the fifo to be used
* @sgl: pointer to the scatterlist array
* @nents: number of entries in the scatterlist array
* @len: number of elements to transfer
*
* This macro fills a scatterlist for DMA input.
* It returns the number entries in the scatterlist array.
*
* Note that with only one concurrent reader and one concurrent
* writer, you don't need extra locking to use these macros.
*/
#define kfifo_dma_in_prepare(fifo, sgl, nents, len) \
({ \
typeof((fifo) + 1) __tmp = (fifo); \
struct scatterlist *__sgl = (sgl); \
int __nents = (nents); \
unsigned int __len = (len); \
const size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \
(__recsize) ? \
__kfifo_dma_in_prepare_r(__kfifo, __sgl, __nents, __len, __recsize) : \
__kfifo_dma_in_prepare(__kfifo, __sgl, __nents, __len); \
})
/**
* kfifo_dma_in_finish - finish a DMA IN operation
* @fifo: address of the fifo to be used
* @len: number of bytes to received
*
* This macro finish a DMA IN operation. The in counter will be updated by
* the len parameter. No error checking will be done.
*
* Note that with only one concurrent reader and one concurrent
* writer, you don't need extra locking to use these macros.
*/
#define kfifo_dma_in_finish(fifo, len) \
(void)({ \
typeof((fifo) + 1) __tmp = (fifo); \
unsigned int __len = (len); \
const size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \
if (__recsize) \
__kfifo_dma_in_finish_r(__kfifo, __len, __recsize); \
else \
__kfifo->in += __len / sizeof(*__tmp->type); \
})
/**
* kfifo_dma_out_prepare - setup a scatterlist for DMA output
* @fifo: address of the fifo to be used
* @sgl: pointer to the scatterlist array
* @nents: number of entries in the scatterlist array
* @len: number of elements to transfer
*
* This macro fills a scatterlist for DMA output which at most @len bytes
* to transfer.
* It returns the number entries in the scatterlist array.
* A zero means there is no space available and the scatterlist is not filled.
*
* Note that with only one concurrent reader and one concurrent
* writer, you don't need extra locking to use these macros.
*/
#define kfifo_dma_out_prepare(fifo, sgl, nents, len) \
({ \
typeof((fifo) + 1) __tmp = (fifo); \
struct scatterlist *__sgl = (sgl); \
int __nents = (nents); \
unsigned int __len = (len); \
const size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \
(__recsize) ? \
__kfifo_dma_out_prepare_r(__kfifo, __sgl, __nents, __len, __recsize) : \
__kfifo_dma_out_prepare(__kfifo, __sgl, __nents, __len); \
})
/**
* kfifo_dma_out_finish - finish a DMA OUT operation
* @fifo: address of the fifo to be used
* @len: number of bytes transferred
*
* This macro finish a DMA OUT operation. The out counter will be updated by
* the len parameter. No error checking will be done.
*
* Note that with only one concurrent reader and one concurrent
* writer, you don't need extra locking to use these macros.
*/
#define kfifo_dma_out_finish(fifo, len) \
(void)({ \
typeof((fifo) + 1) __tmp = (fifo); \
unsigned int __len = (len); \
const size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \
if (__recsize) \
__kfifo_dma_out_finish_r(__kfifo, __recsize); \
else \
__kfifo->out += __len / sizeof(*__tmp->type); \
})
/**
* kfifo_out_peek - gets some data from the fifo
* @fifo: address of the fifo to be used
* @buf: pointer to the storage buffer
* @n: max. number of elements to get
*
* This macro get the data from the fifo and return the numbers of elements
* copied. The data is not removed from the fifo.
*
* Note that with only one concurrent reader and one concurrent
* writer, you don't need extra locking to use these macro.
*/
#define kfifo_out_peek(fifo, buf, n) \
__kfifo_uint_must_check_helper( \
({ \
typeof((fifo) + 1) __tmp = (fifo); \
typeof(__tmp->ptr) __buf = (buf); \
unsigned long __n = (n); \
const size_t __recsize = sizeof(*__tmp->rectype); \
struct __kfifo *__kfifo = &__tmp->kfifo; \
(__recsize) ? \
__kfifo_out_peek_r(__kfifo, __buf, __n, __recsize) : \
__kfifo_out_peek(__kfifo, __buf, __n); \
}) \
)
extern int __kfifo_alloc(struct __kfifo *fifo, unsigned int size,
size_t esize, gfp_t gfp_mask);
extern void __kfifo_free(struct __kfifo *fifo);
extern int __kfifo_init(struct __kfifo *fifo, void *buffer,
unsigned int size, size_t esize);
extern unsigned int __kfifo_in(struct __kfifo *fifo,
const void *buf, unsigned int len);
extern unsigned int __kfifo_out(struct __kfifo *fifo,
void *buf, unsigned int len);
extern int __kfifo_from_user(struct __kfifo *fifo,
const void __user *from, unsigned long len, unsigned int *copied);
extern int __kfifo_to_user(struct __kfifo *fifo,
void __user *to, unsigned long len, unsigned int *copied);
extern unsigned int __kfifo_dma_in_prepare(struct __kfifo *fifo,
struct scatterlist *sgl, int nents, unsigned int len);
extern unsigned int __kfifo_dma_out_prepare(struct __kfifo *fifo,
struct scatterlist *sgl, int nents, unsigned int len);
extern unsigned int __kfifo_out_peek(struct __kfifo *fifo,
void *buf, unsigned int len);
extern unsigned int __kfifo_in_r(struct __kfifo *fifo,
const void *buf, unsigned int len, size_t recsize);
extern unsigned int __kfifo_out_r(struct __kfifo *fifo,
void *buf, unsigned int len, size_t recsize);
extern int __kfifo_from_user_r(struct __kfifo *fifo,
const void __user *from, unsigned long len, unsigned int *copied,
size_t recsize);
extern int __kfifo_to_user_r(struct __kfifo *fifo, void __user *to,
unsigned long len, unsigned int *copied, size_t recsize);
extern unsigned int __kfifo_dma_in_prepare_r(struct __kfifo *fifo,
struct scatterlist *sgl, int nents, unsigned int len, size_t recsize);
extern void __kfifo_dma_in_finish_r(struct __kfifo *fifo,
unsigned int len, size_t recsize);
extern unsigned int __kfifo_dma_out_prepare_r(struct __kfifo *fifo,
struct scatterlist *sgl, int nents, unsigned int len, size_t recsize);
extern void __kfifo_dma_out_finish_r(struct __kfifo *fifo, size_t recsize);
extern unsigned int __kfifo_len_r(struct __kfifo *fifo, size_t recsize);
extern void __kfifo_skip_r(struct __kfifo *fifo, size_t recsize);
extern unsigned int __kfifo_out_peek_r(struct __kfifo *fifo,
void *buf, unsigned int len, size_t recsize);
extern unsigned int __kfifo_max_r(unsigned int len, size_t recsize);
#endif
+57
View File
@@ -0,0 +1,57 @@
#ifndef _LINUX_KTHREAD_H
#define _LINUX_KTHREAD_H
/*
* Minimal kthread emulation for KolibriOS.
*
* The GPU scheduler (drivers/video/drm/amdgpu/scheduler) is the only user in
* the DRM tree. KolibriOS kernel threads are created with CreateKernelThread(),
* which takes no argument, so kthread_run() stashes the payload in a small
* pid-indexed table and the trampoline picks it up. Park/stop are cooperative
* flags polled by the thread body, matching how the scheduler uses them.
*/
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/err.h>
#include <linux/rwsem.h>
/*
* Placeholder address space. Drivers reach it as current->mm on their userptr
* paths only, which KolibriOS never enters (no ioctl surface for user code).
*/
struct mm_struct {
struct rw_semaphore mmap_sem;
};
struct task_struct {
int (*threadfn)(void *data);
void *data;
int pid;
volatile int should_stop;
volatile int should_park;
volatile int parked;
char comm[16];
struct mm_struct *mm;
};
struct task_struct *kthread_create_kos(int (*threadfn)(void *data),
void *data, const char *name);
int kthread_stop(struct task_struct *k);
bool kthread_should_stop(void);
bool kthread_should_park(void);
void kthread_parkme(void);
int kthread_park(struct task_struct *k);
void kthread_unpark(struct task_struct *k);
struct task_struct *kthread_current(void);
#define kthread_run(threadfn, data, namefmt, ...) \
kthread_create_kos((threadfn), (data), (namefmt))
#define kthread_create(threadfn, data, namefmt, ...) \
kthread_create_kos((threadfn), (data), (namefmt))
static inline void wake_up_process(struct task_struct *k) { }
static inline void get_task_struct(struct task_struct *k) { }
static inline void put_task_struct(struct task_struct *k) { }
#endif /* _LINUX_KTHREAD_H */
+24
View File
@@ -0,0 +1,24 @@
#ifndef _LINUX_MFD_CORE_H
#define _LINUX_MFD_CORE_H
/*
* No multi-function-device bus on KolibriOS. amdgpu_acp.h embeds an
* mfd_cell pointer in struct amdgpu_acp; the ACP block itself is not built.
*/
#include <linux/types.h>
struct device;
struct resource;
struct mfd_cell {
const char *name;
int id;
void *platform_data;
size_t pdata_size;
int num_resources;
const struct resource *resources;
};
static inline int mfd_add_hotplug_devices(struct device *parent,
const struct mfd_cell *cells, int n)
{ return -ENODEV; }
static inline void mfd_remove_devices(struct device *parent) { }
#endif
+6
View File
@@ -8,6 +8,12 @@
#define nth_page(page,n) ((void*)(((page_to_phys(page)>>12)+(n))<<12))
#define __page_to_pfn(page) (page_to_phys(page)>>12)
/*
* A struct page * here is just the physical address (see page_to_phys() in
* <linux/kernel.h>), so the reverse direction is the same shift back.
*/
#define __pfn_to_page(pfn) ((struct page *)((dma_addr_t)(pfn) << 12))
#define pfn_to_page(pfn) __pfn_to_page(pfn)
/* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) ALIGN(addr, PAGE_SIZE)
+10
View File
@@ -26,4 +26,14 @@
struct module {};
/*
* Nothing is a module here - everything is linked into the one image - so the
* reference count can never drop and a request for another module can never be
* satisfied. Implemented in the driver's kos_* glue.
*/
extern int request_module(const char *name, ...);
extern int try_module_get(struct module *module);
extern void module_put(struct module *module);
#endif /* _LINUX_MODULE_H */
+9
View File
@@ -77,6 +77,15 @@ void __attribute__ ((fastcall)) __attribute__ ((dllimport))
void __attribute__ ((fastcall)) __attribute__ ((dllimport))
mutex_unlock(struct mutex*)__asm__("MutexUnlock");
/*
* mutex_init() is the DDK's MutexInit(); these two are the spellings upstream
* code reaches for when it wants a lockdep class, which this port does not
* have. Both end up in the same place.
*/
extern void __mutex_init(struct mutex *lock, const char *name,
struct lock_class_key *key);
extern void mutex_lock_nested(struct mutex *lock, unsigned int subclass);
static inline int mutex_lock_interruptible(struct mutex *lock)
{
mutex_lock(lock);
+10
View File
@@ -0,0 +1,10 @@
#ifndef _LINUX_OF_DEVICE_H
#define _LINUX_OF_DEVICE_H
/* No device tree on x86; pulled in unconditionally by nvif/os.h. */
struct device;
struct of_device_id;
static inline const struct of_device_id *
of_match_device(const struct of_device_id *m, const struct device *dev)
{ return NULL; }
#endif
+8
View File
@@ -0,0 +1,8 @@
#ifndef _LINUX_PAGEMAP_H
#define _LINUX_PAGEMAP_H
/* Only the shift/size helpers are used by the TTM/GEM paths on this port. */
#include <linux/mm.h>
#define PAGE_CACHE_SHIFT PAGE_SHIFT
#define PAGE_CACHE_SIZE PAGE_SIZE
#define PAGE_CACHE_MASK PAGE_MASK
#endif
+7
View File
@@ -275,6 +275,13 @@ struct pci_dev {
struct pci_bus *bus; /* bus this device is on */
struct pci_bus *subordinate; /* bus this device bridges to */
/*
* Always NULL on this port: there is no driver model to bind through.
* nouveau_drm.c reads it to decide whether the HDMI audio function is
* claimed before powering the GPU down, and takes the safe branch.
*/
struct pci_driver *driver;
void *sysdata; /* hook for sys-specific extension */
// struct proc_dir_entry *procent; /* device entry in /proc/bus/pci */
struct pci_slot *slot; /* Physical slot this device is in */
+7
View File
@@ -0,0 +1,7 @@
#ifndef _LINUX_PLATFORM_DEVICE_H
#define _LINUX_PLATFORM_DEVICE_H
/* No platform bus; amdgpu_drv.h only needs the type to exist. */
#include <linux/device.h>
struct platform_device { struct device dev; const char *name; int id; };
struct platform_driver;
#endif
+12
View File
@@ -0,0 +1,12 @@
#ifndef _LINUX_POWER_SUPPLY_H
#define _LINUX_POWER_SUPPLY_H
/*
* No battery subsystem on KolibriOS. power_supply_is_system_supplied() is
* already provided by <syscall.h>; only the enum labels are missing.
*/
enum {
POWER_SUPPLY_TYPE_UNKNOWN = 0,
POWER_SUPPLY_TYPE_BATTERY,
POWER_SUPPLY_TYPE_MAINS,
};
#endif
+22
View File
@@ -0,0 +1,22 @@
#ifndef _LINUX_REBOOT_H
#define _LINUX_REBOOT_H
/*
* No reboot notifier chain on this port. nvif/os.h includes this header for
* every nvkm translation unit; nothing in the built set registers a notifier.
*/
#include <linux/notifier.h>
#define SYS_RESTART 0x0001
#define SYS_HALT 0x0002
#define SYS_POWER_OFF 0x0003
static inline int register_reboot_notifier(struct notifier_block *nb) { return 0; }
static inline int unregister_reboot_notifier(struct notifier_block *nb) { return 0; }
/*
* nvkm/subdev/therm/temp.c asks for this when the GPU passes its shutdown
* threshold. There is no orderly shutdown to request on KolibriOS; the
* driver's implementation logs and returns.
*/
extern int orderly_poweroff(bool force);
#endif
@@ -0,0 +1,18 @@
#ifndef _LINUX_REGULATOR_CONSUMER_H
#define _LINUX_REGULATOR_CONSUMER_H
/* Tegra-only; see linux/clk.h for why this exists at all. */
#include <linux/errno.h>
#include <linux/err.h>
struct regulator;
struct device;
static inline struct regulator *regulator_get(struct device *dev, const char *id)
{ return ERR_PTR(-ENOENT); }
static inline void regulator_put(struct regulator *r) { }
static inline int regulator_enable(struct regulator *r) { return -ENOSYS; }
static inline int regulator_disable(struct regulator *r) { return -ENOSYS; }
static inline int regulator_get_voltage(struct regulator *r) { return -ENODEV; }
static inline int regulator_set_voltage(struct regulator *r, int min_uV, int max_uV)
{ return -ENODEV; }
#endif
+15
View File
@@ -0,0 +1,15 @@
#ifndef _LINUX_RESET_H
#define _LINUX_RESET_H
/* Tegra-only; see linux/clk.h for why this exists at all. */
#include <linux/errno.h>
#include <linux/err.h>
struct reset_control;
struct device;
static inline struct reset_control *reset_control_get(struct device *dev, const char *id)
{ return ERR_PTR(-ENOENT); }
static inline void reset_control_put(struct reset_control *rstc) { }
static inline int reset_control_assert(struct reset_control *rstc) { return -ENOSYS; }
static inline int reset_control_deassert(struct reset_control *rstc) { return -ENOSYS; }
#endif
+10
View File
@@ -49,4 +49,14 @@
#define schedule_timeout(x) delay(x)
#define MAX_SCHEDULE_TIMEOUT LONG_MAX
/*
* No processes and no signals behind a driver thread: signal_pending() is
* always false, so interruptible waits only ever end on their timeout, and
* every task carries the singleton name set in kos_stubs.c.
*/
struct task_struct;
extern int signal_pending(struct task_struct *p);
extern void __set_current_state(int state);
extern char *get_task_comm(char *buf, struct task_struct *tsk);
#endif
+19
View File
@@ -0,0 +1,19 @@
#ifndef _LINUX_SCREEN_INFO_H
#define _LINUX_SCREEN_INFO_H
/*
* nouveau_fbcon.c only uses this to decide whether it owns the boot console.
* KolibriOS has no boot console to hand over, so the record stays empty.
*/
#include <linux/types.h>
struct screen_info {
__u8 orig_video_isVGA;
__u16 lfb_width;
__u16 lfb_height;
__u16 lfb_depth;
__u32 lfb_base;
__u32 lfb_size;
};
extern struct screen_info screen_info;
#endif
+5
View File
@@ -0,0 +1,5 @@
#ifndef _LINUX_SWIOTLB_H
#define _LINUX_SWIOTLB_H
/* No bounce buffers on this port; amdgpu_ttm.c only queries swiotlb_nr_tbl(). */
static inline unsigned long swiotlb_nr_tbl(void) { return 0; }
#endif
+35
View File
@@ -0,0 +1,35 @@
#ifndef _LINUX_TRACEPOINT_H
#define _LINUX_TRACEPOINT_H
/* Tracepoints compile away: amdgpu_trace.h expands to empty trace_*() calls. */
/*
* Each event still has to yield a callable trace_<name>(), because the driver
* code calls it unconditionally - upstream generates one per event. Here they
* expand to empty inlines, so the calls disappear at -O2 but the argument
* expressions are still type-checked.
*/
#define TP_PROTO(args...) args
#define TP_ARGS(args...) args
#define TP_STRUCT__entry(args...)
#define TP_fast_assign(args...)
#define TP_printk(fmt, args...)
#define TP_CONDITION(args...)
#define DECLARE_EVENT_CLASS(name, proto, args, tstruct, assign, print)
#define DEFINE_EVENT(tmpl, name, proto, args) \
static inline void trace_##name(proto) { } \
static inline bool trace_##name##_enabled(void) { return false; }
#define TRACE_EVENT(name, proto, args, tstruct, assign, print) \
static inline void trace_##name(proto) { } \
static inline bool trace_##name##_enabled(void) { return false; }
#define TRACE_EVENT_CONDITION(name, proto, args, cond, tstruct, assign, print) \
static inline void trace_##name(proto) { } \
static inline bool trace_##name##_enabled(void) { return false; }
#define DECLARE_TRACE(name, proto, args) \
static inline void trace_##name(proto) { }
#define EXPORT_TRACEPOINT_SYMBOL_GPL(name)
#define EXPORT_TRACEPOINT_SYMBOL(name)
#endif
+5
View File
@@ -0,0 +1,5 @@
#ifndef _LINUX_TTY_H
#define _LINUX_TTY_H
/* No tty layer; nouveau_fbcon.c includes it for console_lock() neighbours. */
#include <linux/console.h>
#endif
+1
View File
@@ -188,6 +188,7 @@ static inline enum vga_switcheroo_handler_flags_t vga_switcheroo_handler_flags(v
static inline int vga_switcheroo_lock_ddc(struct pci_dev *pdev) { return -ENODEV; }
static inline int vga_switcheroo_unlock_ddc(struct pci_dev *pdev) { return -ENODEV; }
static inline int vga_switcheroo_process_delayed_switch(void) { return 0; }
static inline bool vga_switcheroo_client_probe_defer(struct pci_dev *pdev) { return false; }
static inline enum vga_switcheroo_state vga_switcheroo_get_client_state(struct pci_dev *dev) { return VGA_SWITCHEROO_ON; }
static inline void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev, enum vga_switcheroo_state dynamic) {}
+6
View File
@@ -30,6 +30,12 @@ extern void *vmalloc(unsigned long size);
extern void *vzalloc(unsigned long size);
extern void vfree(const void *addr);
/*
* kmalloc() and vmalloc() come from the same allocator on this port, so one
* free serves both - which is what kvfree() means upstream too.
*/
extern void kvfree(const void *addr);
extern void *vmap(struct page **pages, unsigned int count,
unsigned long flags, pgprot_t prot);
extern void vunmap(const void *addr);
+24
View File
@@ -326,6 +326,30 @@ int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *
#define DEFINE_WAIT(name) DEFINE_WAIT_FUNC(name, autoremove_wake_function)
/*
* The "_locked" variants are entered with wq.lock already held and must give
* it up while waiting. That rules out the event-based path above, which takes
* the lock itself, so these poll instead - the same trade the rest of this
* header already makes.
*
* Because nothing ever blocks on an event here, wake_up_all_locked() has
* nothing to signal: the waiter re-tests the condition on its next tick.
*/
#define wait_event_interruptible_locked(wq, condition) \
({ \
while (!(condition)) { \
spin_unlock(&(wq).lock); \
delay(1); \
spin_lock(&(wq).lock); \
} \
0; \
})
#define wait_event_locked(wq, condition) \
wait_event_interruptible_locked(wq, condition)
#define wake_up_locked(q) do { } while (0)
#define wake_up_all_locked(q) do { } while (0)
#endif
+3
View File
@@ -268,6 +268,9 @@ static inline bool mod_delayed_work(struct workqueue_struct *wq,
(_work)->work.func = _func; \
} while (0)
/* Defined in each driver's kos_kernel.c. */
extern bool flush_work(struct work_struct *work);
static inline bool schedule_work(struct work_struct *work)
{
return queue_work(system_wq, work);
+5
View File
@@ -0,0 +1,5 @@
#ifndef __SOC_TEGRA_FUSE_H
#define __SOC_TEGRA_FUSE_H
/* Tegra-only; nvif/os.h includes it unconditionally. */
static inline int tegra_sku_info_dummy(void) { return 0; }
#endif
+5
View File
@@ -0,0 +1,5 @@
#ifndef __SOC_TEGRA_PMC_H
#define __SOC_TEGRA_PMC_H
/* Tegra-only; nvif/os.h includes it unconditionally. */
static inline int tegra_pmc_dummy(void) { return 0; }
#endif
+5
View File
@@ -0,0 +1,5 @@
#ifndef _TRACE_DEFINE_TRACE_H
#define _TRACE_DEFINE_TRACE_H
/* Tracepoints are compiled out - see linux/tracepoint.h. */
#undef TRACE_HEADER_MULTI_READ
#endif
+6
View File
@@ -0,0 +1,6 @@
#ifndef _TRACE_EVENTS_FENCE_H
#define _TRACE_EVENTS_FENCE_H
/* Tracepoints are compiled out; nouveau_fence.c is the only includer. */
struct fence;
static inline void trace_fence_emit(struct fence *fence) { }
#endif
+8 -1
View File
@@ -68,7 +68,14 @@
((nr) << _IOC_NRSHIFT) | \
((size) << _IOC_SIZESHIFT))
#ifndef __KERNEL__
#ifdef __KERNEL__
/* provoke compile error for invalid uses of size argument */
extern unsigned int __invalid_size_argument_for_IOC;
#define _IOC_TYPECHECK(t) \
((sizeof(t) == sizeof(t[1]) && \
sizeof(t) < (1 << _IOC_SIZEBITS)) ? \
sizeof(t) : __invalid_size_argument_for_IOC)
#else
#define _IOC_TYPECHECK(t) (sizeof(t))
#endif
+662
View File
@@ -0,0 +1,662 @@
/* amdgpu_drm.h -- Public header for the amdgpu driver -*- linux-c -*-
*
* Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Fremont, California.
* Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas.
* 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.
*
* Authors:
* Kevin E. Martin <martin@valinux.com>
* Gareth Hughes <gareth@valinux.com>
* Keith Whitwell <keith@tungstengraphics.com>
*/
#ifndef __AMDGPU_DRM_H__
#define __AMDGPU_DRM_H__
#include "drm.h"
#if defined(__cplusplus)
extern "C" {
#endif
#define DRM_AMDGPU_GEM_CREATE 0x00
#define DRM_AMDGPU_GEM_MMAP 0x01
#define DRM_AMDGPU_CTX 0x02
#define DRM_AMDGPU_BO_LIST 0x03
#define DRM_AMDGPU_CS 0x04
#define DRM_AMDGPU_INFO 0x05
#define DRM_AMDGPU_GEM_METADATA 0x06
#define DRM_AMDGPU_GEM_WAIT_IDLE 0x07
#define DRM_AMDGPU_GEM_VA 0x08
#define DRM_AMDGPU_WAIT_CS 0x09
#define DRM_AMDGPU_GEM_OP 0x10
#define DRM_AMDGPU_GEM_USERPTR 0x11
#define DRM_IOCTL_AMDGPU_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_CREATE, union drm_amdgpu_gem_create)
#define DRM_IOCTL_AMDGPU_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_MMAP, union drm_amdgpu_gem_mmap)
#define DRM_IOCTL_AMDGPU_CTX DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_CTX, union drm_amdgpu_ctx)
#define DRM_IOCTL_AMDGPU_BO_LIST DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_BO_LIST, union drm_amdgpu_bo_list)
#define DRM_IOCTL_AMDGPU_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_CS, union drm_amdgpu_cs)
#define DRM_IOCTL_AMDGPU_INFO DRM_IOW(DRM_COMMAND_BASE + DRM_AMDGPU_INFO, struct drm_amdgpu_info)
#define DRM_IOCTL_AMDGPU_GEM_METADATA DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_METADATA, struct drm_amdgpu_gem_metadata)
#define DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_WAIT_IDLE, union drm_amdgpu_gem_wait_idle)
#define DRM_IOCTL_AMDGPU_GEM_VA DRM_IOW(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_VA, struct drm_amdgpu_gem_va)
#define DRM_IOCTL_AMDGPU_WAIT_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_WAIT_CS, union drm_amdgpu_wait_cs)
#define DRM_IOCTL_AMDGPU_GEM_OP DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_OP, struct drm_amdgpu_gem_op)
#define DRM_IOCTL_AMDGPU_GEM_USERPTR DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_USERPTR, struct drm_amdgpu_gem_userptr)
#define AMDGPU_GEM_DOMAIN_CPU 0x1
#define AMDGPU_GEM_DOMAIN_GTT 0x2
#define AMDGPU_GEM_DOMAIN_VRAM 0x4
#define AMDGPU_GEM_DOMAIN_GDS 0x8
#define AMDGPU_GEM_DOMAIN_GWS 0x10
#define AMDGPU_GEM_DOMAIN_OA 0x20
/* Flag that CPU access will be required for the case of VRAM domain */
#define AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED (1 << 0)
/* Flag that CPU access will not work, this VRAM domain is invisible */
#define AMDGPU_GEM_CREATE_NO_CPU_ACCESS (1 << 1)
/* Flag that USWC attributes should be used for GTT */
#define AMDGPU_GEM_CREATE_CPU_GTT_USWC (1 << 2)
/* Flag that the memory should be in VRAM and cleared */
#define AMDGPU_GEM_CREATE_VRAM_CLEARED (1 << 3)
/* Flag that create shadow bo(GTT) while allocating vram bo */
#define AMDGPU_GEM_CREATE_SHADOW (1 << 4)
struct drm_amdgpu_gem_create_in {
/** the requested memory size */
__u64 bo_size;
/** physical start_addr alignment in bytes for some HW requirements */
__u64 alignment;
/** the requested memory domains */
__u64 domains;
/** allocation flags */
__u64 domain_flags;
};
struct drm_amdgpu_gem_create_out {
/** returned GEM object handle */
__u32 handle;
__u32 _pad;
};
union drm_amdgpu_gem_create {
struct drm_amdgpu_gem_create_in in;
struct drm_amdgpu_gem_create_out out;
};
/** Opcode to create new residency list. */
#define AMDGPU_BO_LIST_OP_CREATE 0
/** Opcode to destroy previously created residency list */
#define AMDGPU_BO_LIST_OP_DESTROY 1
/** Opcode to update resource information in the list */
#define AMDGPU_BO_LIST_OP_UPDATE 2
struct drm_amdgpu_bo_list_in {
/** Type of operation */
__u32 operation;
/** Handle of list or 0 if we want to create one */
__u32 list_handle;
/** Number of BOs in list */
__u32 bo_number;
/** Size of each element describing BO */
__u32 bo_info_size;
/** Pointer to array describing BOs */
__u64 bo_info_ptr;
};
struct drm_amdgpu_bo_list_entry {
/** Handle of BO */
__u32 bo_handle;
/** New (if specified) BO priority to be used during migration */
__u32 bo_priority;
};
struct drm_amdgpu_bo_list_out {
/** Handle of resource list */
__u32 list_handle;
__u32 _pad;
};
union drm_amdgpu_bo_list {
struct drm_amdgpu_bo_list_in in;
struct drm_amdgpu_bo_list_out out;
};
/* context related */
#define AMDGPU_CTX_OP_ALLOC_CTX 1
#define AMDGPU_CTX_OP_FREE_CTX 2
#define AMDGPU_CTX_OP_QUERY_STATE 3
/* GPU reset status */
#define AMDGPU_CTX_NO_RESET 0
/* this the context caused it */
#define AMDGPU_CTX_GUILTY_RESET 1
/* some other context caused it */
#define AMDGPU_CTX_INNOCENT_RESET 2
/* unknown cause */
#define AMDGPU_CTX_UNKNOWN_RESET 3
struct drm_amdgpu_ctx_in {
/** AMDGPU_CTX_OP_* */
__u32 op;
/** For future use, no flags defined so far */
__u32 flags;
__u32 ctx_id;
__u32 _pad;
};
union drm_amdgpu_ctx_out {
struct {
__u32 ctx_id;
__u32 _pad;
} alloc;
struct {
/** For future use, no flags defined so far */
__u64 flags;
/** Number of resets caused by this context so far. */
__u32 hangs;
/** Reset status since the last call of the ioctl. */
__u32 reset_status;
} state;
};
union drm_amdgpu_ctx {
struct drm_amdgpu_ctx_in in;
union drm_amdgpu_ctx_out out;
};
/*
* This is not a reliable API and you should expect it to fail for any
* number of reasons and have fallback path that do not use userptr to
* perform any operation.
*/
#define AMDGPU_GEM_USERPTR_READONLY (1 << 0)
#define AMDGPU_GEM_USERPTR_ANONONLY (1 << 1)
#define AMDGPU_GEM_USERPTR_VALIDATE (1 << 2)
#define AMDGPU_GEM_USERPTR_REGISTER (1 << 3)
struct drm_amdgpu_gem_userptr {
__u64 addr;
__u64 size;
/* AMDGPU_GEM_USERPTR_* */
__u32 flags;
/* Resulting GEM handle */
__u32 handle;
};
/* same meaning as the GB_TILE_MODE and GL_MACRO_TILE_MODE fields */
#define AMDGPU_TILING_ARRAY_MODE_SHIFT 0
#define AMDGPU_TILING_ARRAY_MODE_MASK 0xf
#define AMDGPU_TILING_PIPE_CONFIG_SHIFT 4
#define AMDGPU_TILING_PIPE_CONFIG_MASK 0x1f
#define AMDGPU_TILING_TILE_SPLIT_SHIFT 9
#define AMDGPU_TILING_TILE_SPLIT_MASK 0x7
#define AMDGPU_TILING_MICRO_TILE_MODE_SHIFT 12
#define AMDGPU_TILING_MICRO_TILE_MODE_MASK 0x7
#define AMDGPU_TILING_BANK_WIDTH_SHIFT 15
#define AMDGPU_TILING_BANK_WIDTH_MASK 0x3
#define AMDGPU_TILING_BANK_HEIGHT_SHIFT 17
#define AMDGPU_TILING_BANK_HEIGHT_MASK 0x3
#define AMDGPU_TILING_MACRO_TILE_ASPECT_SHIFT 19
#define AMDGPU_TILING_MACRO_TILE_ASPECT_MASK 0x3
#define AMDGPU_TILING_NUM_BANKS_SHIFT 21
#define AMDGPU_TILING_NUM_BANKS_MASK 0x3
#define AMDGPU_TILING_SET(field, value) \
(((value) & AMDGPU_TILING_##field##_MASK) << AMDGPU_TILING_##field##_SHIFT)
#define AMDGPU_TILING_GET(value, field) \
(((value) >> AMDGPU_TILING_##field##_SHIFT) & AMDGPU_TILING_##field##_MASK)
#define AMDGPU_GEM_METADATA_OP_SET_METADATA 1
#define AMDGPU_GEM_METADATA_OP_GET_METADATA 2
/** The same structure is shared for input/output */
struct drm_amdgpu_gem_metadata {
/** GEM Object handle */
__u32 handle;
/** Do we want get or set metadata */
__u32 op;
struct {
/** For future use, no flags defined so far */
__u64 flags;
/** family specific tiling info */
__u64 tiling_info;
__u32 data_size_bytes;
__u32 data[64];
} data;
};
struct drm_amdgpu_gem_mmap_in {
/** the GEM object handle */
__u32 handle;
__u32 _pad;
};
struct drm_amdgpu_gem_mmap_out {
/** mmap offset from the vma offset manager */
__u64 addr_ptr;
};
union drm_amdgpu_gem_mmap {
struct drm_amdgpu_gem_mmap_in in;
struct drm_amdgpu_gem_mmap_out out;
};
struct drm_amdgpu_gem_wait_idle_in {
/** GEM object handle */
__u32 handle;
/** For future use, no flags defined so far */
__u32 flags;
/** Absolute timeout to wait */
__u64 timeout;
};
struct drm_amdgpu_gem_wait_idle_out {
/** BO status: 0 - BO is idle, 1 - BO is busy */
__u32 status;
/** Returned current memory domain */
__u32 domain;
};
union drm_amdgpu_gem_wait_idle {
struct drm_amdgpu_gem_wait_idle_in in;
struct drm_amdgpu_gem_wait_idle_out out;
};
struct drm_amdgpu_wait_cs_in {
/** Command submission handle */
__u64 handle;
/** Absolute timeout to wait */
__u64 timeout;
__u32 ip_type;
__u32 ip_instance;
__u32 ring;
__u32 ctx_id;
};
struct drm_amdgpu_wait_cs_out {
/** CS status: 0 - CS completed, 1 - CS still busy */
__u64 status;
};
union drm_amdgpu_wait_cs {
struct drm_amdgpu_wait_cs_in in;
struct drm_amdgpu_wait_cs_out out;
};
#define AMDGPU_GEM_OP_GET_GEM_CREATE_INFO 0
#define AMDGPU_GEM_OP_SET_PLACEMENT 1
/* Sets or returns a value associated with a buffer. */
struct drm_amdgpu_gem_op {
/** GEM object handle */
__u32 handle;
/** AMDGPU_GEM_OP_* */
__u32 op;
/** Input or return value */
__u64 value;
};
#define AMDGPU_VA_OP_MAP 1
#define AMDGPU_VA_OP_UNMAP 2
/* Delay the page table update till the next CS */
#define AMDGPU_VM_DELAY_UPDATE (1 << 0)
/* Mapping flags */
/* readable mapping */
#define AMDGPU_VM_PAGE_READABLE (1 << 1)
/* writable mapping */
#define AMDGPU_VM_PAGE_WRITEABLE (1 << 2)
/* executable mapping, new for VI */
#define AMDGPU_VM_PAGE_EXECUTABLE (1 << 3)
struct drm_amdgpu_gem_va {
/** GEM object handle */
__u32 handle;
__u32 _pad;
/** AMDGPU_VA_OP_* */
__u32 operation;
/** AMDGPU_VM_PAGE_* */
__u32 flags;
/** va address to assign . Must be correctly aligned.*/
__u64 va_address;
/** Specify offset inside of BO to assign. Must be correctly aligned.*/
__u64 offset_in_bo;
/** Specify mapping size. Must be correctly aligned. */
__u64 map_size;
};
#define AMDGPU_HW_IP_GFX 0
#define AMDGPU_HW_IP_COMPUTE 1
#define AMDGPU_HW_IP_DMA 2
#define AMDGPU_HW_IP_UVD 3
#define AMDGPU_HW_IP_VCE 4
#define AMDGPU_HW_IP_NUM 5
#define AMDGPU_HW_IP_INSTANCE_MAX_COUNT 1
#define AMDGPU_CHUNK_ID_IB 0x01
#define AMDGPU_CHUNK_ID_FENCE 0x02
#define AMDGPU_CHUNK_ID_DEPENDENCIES 0x03
struct drm_amdgpu_cs_chunk {
__u32 chunk_id;
__u32 length_dw;
__u64 chunk_data;
};
struct drm_amdgpu_cs_in {
/** Rendering context id */
__u32 ctx_id;
/** Handle of resource list associated with CS */
__u32 bo_list_handle;
__u32 num_chunks;
__u32 _pad;
/** this points to __u64 * which point to cs chunks */
__u64 chunks;
};
struct drm_amdgpu_cs_out {
__u64 handle;
};
union drm_amdgpu_cs {
struct drm_amdgpu_cs_in in;
struct drm_amdgpu_cs_out out;
};
/* Specify flags to be used for IB */
/* This IB should be submitted to CE */
#define AMDGPU_IB_FLAG_CE (1<<0)
/* CE Preamble */
#define AMDGPU_IB_FLAG_PREAMBLE (1<<1)
struct drm_amdgpu_cs_chunk_ib {
__u32 _pad;
/** AMDGPU_IB_FLAG_* */
__u32 flags;
/** Virtual address to begin IB execution */
__u64 va_start;
/** Size of submission */
__u32 ib_bytes;
/** HW IP to submit to */
__u32 ip_type;
/** HW IP index of the same type to submit to */
__u32 ip_instance;
/** Ring index to submit to */
__u32 ring;
};
struct drm_amdgpu_cs_chunk_dep {
__u32 ip_type;
__u32 ip_instance;
__u32 ring;
__u32 ctx_id;
__u64 handle;
};
struct drm_amdgpu_cs_chunk_fence {
__u32 handle;
__u32 offset;
};
struct drm_amdgpu_cs_chunk_data {
union {
struct drm_amdgpu_cs_chunk_ib ib_data;
struct drm_amdgpu_cs_chunk_fence fence_data;
};
};
/**
* Query h/w info: Flag that this is integrated (a.h.a. fusion) GPU
*
*/
#define AMDGPU_IDS_FLAGS_FUSION 0x1
/* indicate if acceleration can be working */
#define AMDGPU_INFO_ACCEL_WORKING 0x00
/* get the crtc_id from the mode object id? */
#define AMDGPU_INFO_CRTC_FROM_ID 0x01
/* query hw IP info */
#define AMDGPU_INFO_HW_IP_INFO 0x02
/* query hw IP instance count for the specified type */
#define AMDGPU_INFO_HW_IP_COUNT 0x03
/* timestamp for GL_ARB_timer_query */
#define AMDGPU_INFO_TIMESTAMP 0x05
/* Query the firmware version */
#define AMDGPU_INFO_FW_VERSION 0x0e
/* Subquery id: Query VCE firmware version */
#define AMDGPU_INFO_FW_VCE 0x1
/* Subquery id: Query UVD firmware version */
#define AMDGPU_INFO_FW_UVD 0x2
/* Subquery id: Query GMC firmware version */
#define AMDGPU_INFO_FW_GMC 0x03
/* Subquery id: Query GFX ME firmware version */
#define AMDGPU_INFO_FW_GFX_ME 0x04
/* Subquery id: Query GFX PFP firmware version */
#define AMDGPU_INFO_FW_GFX_PFP 0x05
/* Subquery id: Query GFX CE firmware version */
#define AMDGPU_INFO_FW_GFX_CE 0x06
/* Subquery id: Query GFX RLC firmware version */
#define AMDGPU_INFO_FW_GFX_RLC 0x07
/* Subquery id: Query GFX MEC firmware version */
#define AMDGPU_INFO_FW_GFX_MEC 0x08
/* Subquery id: Query SMC firmware version */
#define AMDGPU_INFO_FW_SMC 0x0a
/* Subquery id: Query SDMA firmware version */
#define AMDGPU_INFO_FW_SDMA 0x0b
/* number of bytes moved for TTM migration */
#define AMDGPU_INFO_NUM_BYTES_MOVED 0x0f
/* the used VRAM size */
#define AMDGPU_INFO_VRAM_USAGE 0x10
/* the used GTT size */
#define AMDGPU_INFO_GTT_USAGE 0x11
/* Information about GDS, etc. resource configuration */
#define AMDGPU_INFO_GDS_CONFIG 0x13
/* Query information about VRAM and GTT domains */
#define AMDGPU_INFO_VRAM_GTT 0x14
/* Query information about register in MMR address space*/
#define AMDGPU_INFO_READ_MMR_REG 0x15
/* Query information about device: rev id, family, etc. */
#define AMDGPU_INFO_DEV_INFO 0x16
/* visible vram usage */
#define AMDGPU_INFO_VIS_VRAM_USAGE 0x17
/* number of TTM buffer evictions */
#define AMDGPU_INFO_NUM_EVICTIONS 0x18
#define AMDGPU_INFO_MMR_SE_INDEX_SHIFT 0
#define AMDGPU_INFO_MMR_SE_INDEX_MASK 0xff
#define AMDGPU_INFO_MMR_SH_INDEX_SHIFT 8
#define AMDGPU_INFO_MMR_SH_INDEX_MASK 0xff
struct drm_amdgpu_query_fw {
/** AMDGPU_INFO_FW_* */
__u32 fw_type;
/**
* Index of the IP if there are more IPs of
* the same type.
*/
__u32 ip_instance;
/**
* Index of the engine. Whether this is used depends
* on the firmware type. (e.g. MEC, SDMA)
*/
__u32 index;
__u32 _pad;
};
/* Input structure for the INFO ioctl */
struct drm_amdgpu_info {
/* Where the return value will be stored */
__u64 return_pointer;
/* The size of the return value. Just like "size" in "snprintf",
* it limits how many bytes the kernel can write. */
__u32 return_size;
/* The query request id. */
__u32 query;
union {
struct {
__u32 id;
__u32 _pad;
} mode_crtc;
struct {
/** AMDGPU_HW_IP_* */
__u32 type;
/**
* Index of the IP if there are more IPs of the same
* type. Ignored by AMDGPU_INFO_HW_IP_COUNT.
*/
__u32 ip_instance;
} query_hw_ip;
struct {
__u32 dword_offset;
/** number of registers to read */
__u32 count;
__u32 instance;
/** For future use, no flags defined so far */
__u32 flags;
} read_mmr_reg;
struct drm_amdgpu_query_fw query_fw;
};
};
struct drm_amdgpu_info_gds {
/** GDS GFX partition size */
__u32 gds_gfx_partition_size;
/** GDS compute partition size */
__u32 compute_partition_size;
/** total GDS memory size */
__u32 gds_total_size;
/** GWS size per GFX partition */
__u32 gws_per_gfx_partition;
/** GSW size per compute partition */
__u32 gws_per_compute_partition;
/** OA size per GFX partition */
__u32 oa_per_gfx_partition;
/** OA size per compute partition */
__u32 oa_per_compute_partition;
__u32 _pad;
};
struct drm_amdgpu_info_vram_gtt {
__u64 vram_size;
__u64 vram_cpu_accessible_size;
__u64 gtt_size;
};
struct drm_amdgpu_info_firmware {
__u32 ver;
__u32 feature;
};
#define AMDGPU_VRAM_TYPE_UNKNOWN 0
#define AMDGPU_VRAM_TYPE_GDDR1 1
#define AMDGPU_VRAM_TYPE_DDR2 2
#define AMDGPU_VRAM_TYPE_GDDR3 3
#define AMDGPU_VRAM_TYPE_GDDR4 4
#define AMDGPU_VRAM_TYPE_GDDR5 5
#define AMDGPU_VRAM_TYPE_HBM 6
#define AMDGPU_VRAM_TYPE_DDR3 7
struct drm_amdgpu_info_device {
/** PCI Device ID */
__u32 device_id;
/** Internal chip revision: A0, A1, etc.) */
__u32 chip_rev;
__u32 external_rev;
/** Revision id in PCI Config space */
__u32 pci_rev;
__u32 family;
__u32 num_shader_engines;
__u32 num_shader_arrays_per_engine;
/* in KHz */
__u32 gpu_counter_freq;
__u64 max_engine_clock;
__u64 max_memory_clock;
/* cu information */
__u32 cu_active_number;
__u32 cu_ao_mask;
__u32 cu_bitmap[4][4];
/** Render backend pipe mask. One render backend is CB+DB. */
__u32 enabled_rb_pipes_mask;
__u32 num_rb_pipes;
__u32 num_hw_gfx_contexts;
__u32 _pad;
__u64 ids_flags;
/** Starting virtual address for UMDs. */
__u64 virtual_address_offset;
/** The maximum virtual address */
__u64 virtual_address_max;
/** Required alignment of virtual addresses. */
__u32 virtual_address_alignment;
/** Page table entry - fragment size */
__u32 pte_fragment_size;
__u32 gart_page_size;
/** constant engine ram size*/
__u32 ce_ram_size;
/** video memory type info*/
__u32 vram_type;
/** video memory bit width*/
__u32 vram_bit_width;
/* vce harvesting instance */
__u32 vce_harvest_config;
};
struct drm_amdgpu_info_hw_ip {
/** Version of h/w IP */
__u32 hw_ip_version_major;
__u32 hw_ip_version_minor;
/** Capabilities */
__u64 capabilities_flags;
/** command buffer address start alignment*/
__u32 ib_start_alignment;
/** command buffer size alignment*/
__u32 ib_size_alignment;
/** Bitmask of available rings. Bit 0 means ring 0, etc. */
__u32 available_rings;
__u32 _pad;
};
/*
* Supported GPU families
*/
#define AMDGPU_FAMILY_UNKNOWN 0
#define AMDGPU_FAMILY_SI 110 /* Hainan, Oland, Verde, Pitcairn, Tahiti */
#define AMDGPU_FAMILY_CI 120 /* Bonaire, Hawaii */
#define AMDGPU_FAMILY_KV 125 /* Kaveri, Kabini, Mullins */
#define AMDGPU_FAMILY_VI 130 /* Iceland, Tonga */
#define AMDGPU_FAMILY_CZ 135 /* Carrizo, Stoney */
#if defined(__cplusplus)
}
#endif
#endif
+152
View File
@@ -0,0 +1,152 @@
/*
* Copyright 2005 Stephane Marchesin.
* 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.
*/
#ifndef __NOUVEAU_DRM_H__
#define __NOUVEAU_DRM_H__
#define DRM_NOUVEAU_EVENT_NVIF 0x80000000
#include "drm.h"
#if defined(__cplusplus)
extern "C" {
#endif
#define NOUVEAU_GEM_DOMAIN_CPU (1 << 0)
#define NOUVEAU_GEM_DOMAIN_VRAM (1 << 1)
#define NOUVEAU_GEM_DOMAIN_GART (1 << 2)
#define NOUVEAU_GEM_DOMAIN_MAPPABLE (1 << 3)
#define NOUVEAU_GEM_DOMAIN_COHERENT (1 << 4)
#define NOUVEAU_GEM_TILE_COMP 0x00030000 /* nv50-only */
#define NOUVEAU_GEM_TILE_LAYOUT_MASK 0x0000ff00
#define NOUVEAU_GEM_TILE_16BPP 0x00000001
#define NOUVEAU_GEM_TILE_32BPP 0x00000002
#define NOUVEAU_GEM_TILE_ZETA 0x00000004
#define NOUVEAU_GEM_TILE_NONCONTIG 0x00000008
struct drm_nouveau_gem_info {
__u32 handle;
__u32 domain;
__u64 size;
__u64 offset;
__u64 map_handle;
__u32 tile_mode;
__u32 tile_flags;
};
struct drm_nouveau_gem_new {
struct drm_nouveau_gem_info info;
__u32 channel_hint;
__u32 align;
};
#define NOUVEAU_GEM_MAX_BUFFERS 1024
struct drm_nouveau_gem_pushbuf_bo_presumed {
__u32 valid;
__u32 domain;
__u64 offset;
};
struct drm_nouveau_gem_pushbuf_bo {
__u64 user_priv;
__u32 handle;
__u32 read_domains;
__u32 write_domains;
__u32 valid_domains;
struct drm_nouveau_gem_pushbuf_bo_presumed presumed;
};
#define NOUVEAU_GEM_RELOC_LOW (1 << 0)
#define NOUVEAU_GEM_RELOC_HIGH (1 << 1)
#define NOUVEAU_GEM_RELOC_OR (1 << 2)
#define NOUVEAU_GEM_MAX_RELOCS 1024
struct drm_nouveau_gem_pushbuf_reloc {
__u32 reloc_bo_index;
__u32 reloc_bo_offset;
__u32 bo_index;
__u32 flags;
__u32 data;
__u32 vor;
__u32 tor;
};
#define NOUVEAU_GEM_MAX_PUSH 512
struct drm_nouveau_gem_pushbuf_push {
__u32 bo_index;
__u32 pad;
__u64 offset;
__u64 length;
};
struct drm_nouveau_gem_pushbuf {
__u32 channel;
__u32 nr_buffers;
__u64 buffers;
__u32 nr_relocs;
__u32 nr_push;
__u64 relocs;
__u64 push;
__u32 suffix0;
__u32 suffix1;
__u64 vram_available;
__u64 gart_available;
};
#define NOUVEAU_GEM_CPU_PREP_NOWAIT 0x00000001
#define NOUVEAU_GEM_CPU_PREP_WRITE 0x00000004
struct drm_nouveau_gem_cpu_prep {
__u32 handle;
__u32 flags;
};
struct drm_nouveau_gem_cpu_fini {
__u32 handle;
};
#define DRM_NOUVEAU_GETPARAM 0x00 /* deprecated */
#define DRM_NOUVEAU_SETPARAM 0x01 /* deprecated */
#define DRM_NOUVEAU_CHANNEL_ALLOC 0x02 /* deprecated */
#define DRM_NOUVEAU_CHANNEL_FREE 0x03 /* deprecated */
#define DRM_NOUVEAU_GROBJ_ALLOC 0x04 /* deprecated */
#define DRM_NOUVEAU_NOTIFIEROBJ_ALLOC 0x05 /* deprecated */
#define DRM_NOUVEAU_GPUOBJ_FREE 0x06 /* deprecated */
#define DRM_NOUVEAU_NVIF 0x07
#define DRM_NOUVEAU_GEM_NEW 0x40
#define DRM_NOUVEAU_GEM_PUSHBUF 0x41
#define DRM_NOUVEAU_GEM_CPU_PREP 0x42
#define DRM_NOUVEAU_GEM_CPU_FINI 0x43
#define DRM_NOUVEAU_GEM_INFO 0x44
#define DRM_IOCTL_NOUVEAU_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_NEW, struct drm_nouveau_gem_new)
#define DRM_IOCTL_NOUVEAU_GEM_PUSHBUF DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_PUSHBUF, struct drm_nouveau_gem_pushbuf)
#define DRM_IOCTL_NOUVEAU_GEM_CPU_PREP DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_CPU_PREP, struct drm_nouveau_gem_cpu_prep)
#define DRM_IOCTL_NOUVEAU_GEM_CPU_FINI DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_CPU_FINI, struct drm_nouveau_gem_cpu_fini)
#define DRM_IOCTL_NOUVEAU_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_INFO, struct drm_nouveau_gem_info)
#if defined(__cplusplus)
}
#endif
#endif /* __NOUVEAU_DRM_H__ */
+188
View File
@@ -0,0 +1,188 @@
/*
* 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.
*
*/
#include <linux/module.h>
#include <drm/drm_encoder_slave.h>
/**
* drm_i2c_encoder_init - Initialize an I2C slave encoder
* @dev: DRM device.
* @encoder: Encoder to be attached to the I2C device. You aren't
* required to have called drm_encoder_init() before.
* @adap: I2C adapter that will be used to communicate with
* the device.
* @info: Information that will be used to create the I2C device.
* Required fields are @addr and @type.
*
* Create an I2C device on the specified bus (the module containing its
* driver is transparently loaded) and attach it to the specified
* &drm_encoder_slave. The @slave_funcs field will be initialized with
* the hooks provided by the slave driver.
*
* If @info->platform_data is non-NULL it will be used as the initial
* slave config.
*
* Returns 0 on success or a negative errno on failure, in particular,
* -ENODEV is returned when no matching driver is found.
*/
int drm_i2c_encoder_init(struct drm_device *dev,
struct drm_encoder_slave *encoder,
struct i2c_adapter *adap,
const struct i2c_board_info *info)
{
struct module *module = NULL;
struct i2c_client *client;
struct drm_i2c_encoder_driver *encoder_drv;
int err = 0;
request_module("%s%s", I2C_MODULE_PREFIX, info->type);
client = i2c_new_device(adap, info);
if (!client) {
err = -ENOMEM;
goto fail;
}
if (!client->dev.driver) {
err = -ENODEV;
goto fail_unregister;
}
module = client->dev.driver->owner;
if (!try_module_get(module)) {
err = -ENODEV;
goto fail_unregister;
}
encoder->bus_priv = client;
encoder_drv = to_drm_i2c_encoder_driver(to_i2c_driver(client->dev.driver));
err = encoder_drv->encoder_init(client, dev, encoder);
if (err)
goto fail_module_put;
if (info->platform_data)
encoder->slave_funcs->set_config(&encoder->base,
info->platform_data);
return 0;
fail_module_put:
module_put(module);
fail_unregister:
i2c_unregister_device(client);
fail:
return err;
}
EXPORT_SYMBOL(drm_i2c_encoder_init);
/**
* drm_i2c_encoder_destroy - Unregister the I2C device backing an encoder
* @drm_encoder: Encoder to be unregistered.
*
* This should be called from the @destroy method of an I2C slave
* encoder driver once I2C access is no longer needed.
*/
void drm_i2c_encoder_destroy(struct drm_encoder *drm_encoder)
{
struct drm_encoder_slave *encoder = to_encoder_slave(drm_encoder);
struct i2c_client *client = drm_i2c_encoder_get_client(drm_encoder);
struct module *module = client->dev.driver->owner;
i2c_unregister_device(client);
encoder->bus_priv = NULL;
module_put(module);
}
EXPORT_SYMBOL(drm_i2c_encoder_destroy);
/*
* Wrapper fxns which can be plugged in to drm_encoder_helper_funcs:
*/
static inline const struct drm_encoder_slave_funcs *
get_slave_funcs(struct drm_encoder *enc)
{
return to_encoder_slave(enc)->slave_funcs;
}
void drm_i2c_encoder_dpms(struct drm_encoder *encoder, int mode)
{
get_slave_funcs(encoder)->dpms(encoder, mode);
}
EXPORT_SYMBOL(drm_i2c_encoder_dpms);
bool drm_i2c_encoder_mode_fixup(struct drm_encoder *encoder,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
if (!get_slave_funcs(encoder)->mode_fixup)
return true;
return get_slave_funcs(encoder)->mode_fixup(encoder, mode, adjusted_mode);
}
EXPORT_SYMBOL(drm_i2c_encoder_mode_fixup);
void drm_i2c_encoder_prepare(struct drm_encoder *encoder)
{
drm_i2c_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
}
EXPORT_SYMBOL(drm_i2c_encoder_prepare);
void drm_i2c_encoder_commit(struct drm_encoder *encoder)
{
drm_i2c_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
}
EXPORT_SYMBOL(drm_i2c_encoder_commit);
void drm_i2c_encoder_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
get_slave_funcs(encoder)->mode_set(encoder, mode, adjusted_mode);
}
EXPORT_SYMBOL(drm_i2c_encoder_mode_set);
enum drm_connector_status drm_i2c_encoder_detect(struct drm_encoder *encoder,
struct drm_connector *connector)
{
return get_slave_funcs(encoder)->detect(encoder, connector);
}
EXPORT_SYMBOL(drm_i2c_encoder_detect);
void drm_i2c_encoder_save(struct drm_encoder *encoder)
{
get_slave_funcs(encoder)->save(encoder);
}
EXPORT_SYMBOL(drm_i2c_encoder_save);
void drm_i2c_encoder_restore(struct drm_encoder *encoder)
{
get_slave_funcs(encoder)->restore(encoder);
}
EXPORT_SYMBOL(drm_i2c_encoder_restore);