Skip to content
Open
53 changes: 52 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
DEPRECATED
==========

As of Linux version 6.15, the functionality provided by this module is now provided by the upstream `AMDGPU` kernel driver. For more information see the [patch series](https://lists.freedesktop.org/archives/amd-gfx/2025-January/118399.html)

Before Installing
=================

Expand All @@ -18,7 +23,7 @@ sudo pacman -S linux53-headers

To Install
==========
Clone the repo into a github directory in your home folder:
Clone the repo into a GitHub directory in your home folder:
```
mkdir github
cd github
Expand Down Expand Up @@ -72,3 +77,49 @@ It should output all clients available on that bus:
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- --
70: 70 -- -- -- -- -- -- --
```
If the output it's only dashes, the driver is not working.

Troubleshooting
===============

Some C knowledge may be needed.

### Device not detected by the driver

If the device is not being detected, `sudo i2cdetect -l` will not show any "AURA GPU adapter", and running `sudo dmesg` you should see "Failed to find any valid device".

In this case, the pci id of your device is probably missing. Check the file "pci_ids.h", the id of your device can be found using the command `lspci -vnn`.

### Device is detected by the driver but won't work (not detected by OpenRGB)

In this case `sudo i2cdetect -l` will show the device, but `sudo i2cdetect -y <number>` will show only dashes, like so:
```
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
```
This usually means that the driver is not using the correct line. The known lines are `6` for Polaris cards, and `7` for
Vega cards, but we can only test the cards we have.
Check the function `line_number_from_asic_type` in file `aura-gpu-hw.c`.

If the line for your asic is unknown, the driver will default to line `6` and you will find "Unknown uc line for asic,
defaulting to line <default line>" in the output of `sudo dmesg`.

Although that's been the case up to now, it is possible that the type of card is not enough to choose line, in that case
some work will be needed to select line based on pci_id.

### Multiple GPUs

This driver *should* work with multiple gpus, even of different generations, and allow to configure each one.
Due to limitations (e.g. not having two GPUs) this is not tested. If having multiple GPUs causes real issues, you can
set `MAX_AURA_DEVICES` (currently 4, as you won't usually see more than 4 cards in a system) to `1` so that it behaves
as it did before multi-GPU support.

You can also increase the value if you have more than 4 GPUs. Increasing the number has a cost, don't do it if not
needed, and don't put unrealistic values, `4` should be enough for anyone.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
14.12445ef
20.7ce9965
4 changes: 3 additions & 1 deletion atom/atom.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "atom.h"
#include "atom-names.h"
#include "atom-bits.h"
#include "../debug.h"

#define ATOM_COND_ABOVE 0
#define ATOM_COND_ABOVEOREQUAL 1
Expand Down Expand Up @@ -1305,7 +1306,8 @@ struct atom_context *atom_parse(struct card_info *card, void const *bios)
str = CSTR(idx);
if (*str != '\0') {
pr_info("ATOM BIOS: %s\n", str);
strlcpy(ctx->vbios_version, str, sizeof(ctx->vbios_version));
if (strscpy(ctx->vbios_version, str, sizeof(ctx->vbios_version)) == -E2BIG)
AURA_WARN("Bios version string too long");
}

return ctx;
Expand Down
3 changes: 2 additions & 1 deletion aura-gpu-bios.c
Original file line number Diff line number Diff line change
Expand Up @@ -1236,7 +1236,8 @@ static void _aura_gpu_bios_read_name(

name_str = get_str(context, name_offset, sizeof(context->bios.name) - 1);
if (*name_str != '\0')
strlcpy(context->bios.name, name_str, sizeof(context->bios.name));
if (strscpy(context->bios.name, name_str, sizeof(context->bios.name)) == -E2BIG)
AURA_WARN("Bios name too long");
}

static bool _aura_gpu_bios_is_atom(
Expand Down
101 changes: 76 additions & 25 deletions aura-gpu-hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "aura-gpu-bios.h"
#include "aura-gpu-reg.h"
#include "atom/atom.h"
#include "main.h"

struct ATOM_MASTER_LIST_OF_COMMAND_TABLES {
uint16_t ASIC_Init; //Function Table, used by various SW components,latest version 1.1
Expand Down Expand Up @@ -113,6 +114,11 @@ struct hw_i2c_context {
container_of(ptr, struct hw_i2c_context, atom_card_info) \
)

static struct pci_device_info {
struct pci_dev* device;
struct pci_device_id id;
};

static uint32_t __invalid_read (
struct card_info *info,
uint32_t reg
Expand Down Expand Up @@ -160,7 +166,10 @@ static void mm_write (
#define HW_I2C_READ 0
#define HW_ASSISTED_I2C_STATUS_FAILURE 2
#define HW_ASSISTED_I2C_STATUS_SUCCESS 1
#define UC_LINE_NUMBER 7
#define UC_LINE_NUMBER_POLARIS 6
#define UC_LINE_NUMBER_VEGA 7
#define UC_LINE_NUMBER_DEFAULT 6
#define UC_LINE_NUMBER_DEFAULT_STR "6 (Polaris)" // Default as string, to be used in messages

struct transaction_parameters {
uint8_t ucI2CSpeed;
Expand All @@ -175,6 +184,22 @@ struct transaction_parameters {
uint8_t ucLineNumber;
};

/*
* Returns the line number
*/
static uint8_t line_number_from_asic_type(enum aura_asic_type type){
switch (type) {
case CHIP_POLARIS10:
case CHIP_POLARIS11:
return UC_LINE_NUMBER_POLARIS;
case CHIP_VEGA10:
return UC_LINE_NUMBER_VEGA;
default:
AURA_WARN("Unknown uc line for asic, defaulting to line " UC_LINE_NUMBER_DEFAULT_STR);
return UC_LINE_NUMBER_DEFAULT;
}
}

static error_t aura_gpu_i2c_process_i2c_ch(
struct hw_i2c_context *context,
uint8_t slave_addr,
Expand Down Expand Up @@ -202,7 +227,10 @@ static error_t aura_gpu_i2c_process_i2c_ch(
args.ucTransBytes = 1;
args.ucSlaveAddr = slave_addr << 1;
args.ucRegIndex = offset;
args.ucLineNumber = UC_LINE_NUMBER;

// Find the line tu use for this particular device
enum aura_asic_type type = aura_i2c_adapter_asic_type(&context->adapter);
args.ucLineNumber = line_number_from_asic_type(type);

AURA_DBG("Pre Transaction: addr = %x, offset = %x, rw = %s, count = %d, out = %x",
args.ucSlaveAddr >> 1,
Expand Down Expand Up @@ -411,7 +439,11 @@ static struct hw_i2c_context *aura_gpu_i2c_create (
context->atom_context->scratch = (uint32_t*)context->scratch;
context->atom_context->scratch_size_bytes = sizeof(context->scratch);
context->adapter.owner = THIS_MODULE;
context->adapter.class = I2C_CLASS_DDC;
context->adapter.class = I2C_CLASS_DEPRECATED; /* I2C_CLASS_DDC was removed in kernel version 6.8
* it only appeared in the radeon_i2c kernel driver
* no in-tree module used it
* and class based device detection is discouraged */

context->adapter.dev.parent = &pci_dev->dev;

i2c_set_adapdata(&context->adapter, context);
Expand All @@ -433,37 +465,56 @@ static struct hw_i2c_context *aura_gpu_i2c_create (
return ERR_PTR(err);
}

static struct pci_dev *find_pci_dev (
void
/*
* Stores pci device and id for at most MAX_AURA_DEVICES devices
*/
void find_pci_devs (
struct pci_device_info pci_devs[MAX_AURA_DEVICES]
){
struct pci_dev *pci_dev = NULL;
const struct pci_device_id *match;

while (NULL != (pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev))) {
struct pci_dev* pci_dev;
struct pci_device_id *match;
int matched = 0;

while (
NULL != (pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) &&
matched < MAX_AURA_DEVICES
) {
match = pci_match_id(pciidlist, pci_dev);
if (match)
return pci_dev;
if (match) {
pci_devs[matched].device = pci_dev;
pci_devs[matched].id = *match;
++matched;
}
}

return NULL;
}

struct i2c_adapter *aura_i2c_bios_create (
void
void aura_i2c_bios_create (
struct aura_adapter adapters[MAX_AURA_DEVICES]
){
struct pci_dev *pci_dev = find_pci_dev();
struct hw_i2c_context *context;
// Finds compatible devices
struct pci_device_info pci_devs[] = {
[ 0 ... MAX_AURA_DEVICES ] = { NULL, {0, 0, 0} }
};
find_pci_devs(pci_devs);

if (!pci_dev) {
AURA_ERR("Failed to find a valid pci device");
return NULL;
// check the first slot for failure
if (!pci_devs[0].device) {
AURA_ERR("Failed to find any valid pci device");
}

context = aura_gpu_i2c_create(pci_dev);
if (IS_ERR_OR_NULL(context))
return ERR_PTR(CLEAR_ERR(context));

return &context->adapter;
// Create and stores a context for every device
struct hw_i2c_context *context;
for(int i = 0; i < MAX_AURA_DEVICES; ++i) {
if(pci_devs[i].device) {
context = aura_gpu_i2c_create(pci_devs[i].device);
if (IS_ERR_OR_NULL(context))
adapters[i].adapter = ERR_PTR(CLEAR_ERR(context));

// Stores device and asic type
adapters[i].asic_type = pci_devs[i].id.driver_data;
adapters[i].adapter = &context->adapter;
}
}
}

void aura_i2c_bios_destroy (
Expand Down
6 changes: 4 additions & 2 deletions aura-gpu-hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
#define _UAPI_AURA_GPU_HW_I2C_H

#include <linux/i2c.h>
#include "include/types.h"
#include "main.h"

struct i2c_adapter *aura_i2c_bios_create (
void
void aura_i2c_bios_create (
struct aura_adapter adapters[MAX_AURA_DEVICES]
);

void aura_i2c_bios_destroy (
Expand Down
6 changes: 5 additions & 1 deletion aura-gpu-i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -640,8 +640,12 @@ static struct aura_i2c_context* aura_gpu_i2c_context_create (
context->timeout_interval = GPU_I2C_TIMEOUT_INTERVAL;

context->i2c_adapter.owner = THIS_MODULE;
context->i2c_adapter.class = I2C_CLASS_DDC;
context->i2c_adapter.algo = &aura_gpu_i2c_algo;
context->i2c_adapter.class = I2C_CLASS_DEPRECATED; /* I2C_CLASS_DDC was removed in kernel version 6.8
* it only appeared in the radeon_i2c kernel driver
* no in-tree module used it
* and class based device detection is discouraged */


snprintf(context->i2c_adapter.name, sizeof(context->i2c_adapter.name), "AURA GPU adapter");
i2c_set_adapdata(&context->i2c_adapter, context);
Expand Down
2 changes: 1 addition & 1 deletion dkms.conf
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
MAKE="make TARGET=${kernelver}"
CLEAN="make TARGET=${kernelver} clean"
PACKAGE_NAME="aura-gpu"
PACKAGE_VERSION="14.12445ef"
PACKAGE_VERSION="20.7ce9965"
BUILT_MODULE_NAME[0]="aura-gpu"
DEST_MODULE_LOCATION[0]="/kernel/drivers/hwmon"
AUTOINSTALL="yes"
10 changes: 10 additions & 0 deletions include/types.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _UAPI_INCLUDE_TYPES_H
#define _UAPI_INCLUDE_TYPES_H
#include <linux/module.h>
#include <linux/pci.h>

#include "../asic/asic-types.h"

#ifndef ERROR_TYPE
typedef int error_t;

struct aura_adapter {
struct i2c_adapter* adapter;
enum aura_asic_type asic_type;
};

#define ERROR_TYPE error_t
#endif

Expand Down
42 changes: 35 additions & 7 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,60 @@
#include <linux/module.h>
#include <linux/pci.h>

#include "main.h"
#include "debug.h"
#include "aura-gpu-hw.h"
#include "include/types.h"

static struct i2c_adapter *adapter = NULL;
// Stores i2c_adapters and asic type
static struct aura_adapter adapters[] = {
[0 ... MAX_AURA_DEVICES] = {NULL, CHIP_LAST}
};

static int __init aura_module_init (
void
){
adapter = aura_i2c_bios_create();
if (IS_ERR_OR_NULL(adapter))
CLEAR_ERR(adapter);
// find at most MAX_AURA_DEVICES devices
aura_i2c_bios_create(adapters);

// clears error on all devices
for (int i = 0; i < MAX_AURA_DEVICES; ++i) {
if (IS_ERR(adapters[i].adapter))
CLEAR_ERR(adapters[i].adapter);
}

return 0;
}

static void __exit aura_module_exit (
void
){
if (adapter)
aura_i2c_bios_destroy(adapter);
for (int i = 0; i < MAX_AURA_DEVICES; ++i) {
if (adapters[i].adapter)
aura_i2c_bios_destroy(adapters[i].adapter);
}
}

/*
* Returns the AURA asic type associated to a certain adapter
*/
enum aura_asic_type aura_i2c_adapter_asic_type(struct i2c_adapter* adapter) {
for (int i = 0; i < MAX_AURA_DEVICES; ++i){
// If adapter is not null, matches on adapter number
if (
adapters[i].adapter &&
i2c_adapter_id(adapters[i].adapter) == i2c_adapter_id(adapter)
) {
return adapters[i].asic_type;
}
}
AURA_ERR("Asic_type not registered");
return CHIP_LAST;
}

module_init(aura_module_init);
module_exit(aura_module_exit);


MODULE_AUTHOR("Owen Parry <waldermort@gmail.com>");
MODULE_DESCRIPTION("ASUS AURA SMBus driver");
MODULE_LICENSE("GPL");
13 changes: 13 additions & 0 deletions main.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef _UAPI_AURA_GPU_MAIN_H
#define _UAPI_AURA_GPU_MAIN_H

#define MAX_AURA_DEVICES 4

#include "include/types.h"

/*
* Returns the AURA asic type associated to a certain adapter
*/
enum aura_asic_type aura_i2c_adapter_asic_type(struct i2c_adapter *adapter);

#endif
Loading