mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 10:09:10 +02:00
Several fixes for:
- amdxdna: Fix for a deadlock, a NULL pointer dereference, a suspend
failure, a hang, an out-of-bounds access, a buffer overflow, input
sanitization and other minor fixes.
- dw-dp: An error handling fix
- ethosu: A binary shift overflow fix
- imx: An error handling fix
- logicvc: A dt node reference leak fix
- nouveau: A WARN_ON removal
- samsung-dsim: A memory leak fix
- sharp-memory: A NULL pointer dereference fix
- vmgfx: A reference count and error handling fix
-----BEGIN PGP SIGNATURE-----
iJUEABMJAB0WIQTkHFbLp4ejekA/qfgnX84Zoj2+dgUCaaAF6AAKCRAnX84Zoj2+
dmHFAYD7ArP5sz46K37kEHWE/HIHKnDT52la2KqAfPwRSQr4+ZOj5OO8uhLdTWS2
pMiOvdIBf3zDdAL8ZyTWlrLa4ZdNJemUfe53JGLnJfZ4QYyTVjb8447smgwD84B9
kaMZYBjS2Q==
=xywq
-----END PGP SIGNATURE-----
Merge tag 'drm-misc-fixes-2026-02-26' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-fixes
Several fixes for:
- amdxdna: Fix for a deadlock, a NULL pointer dereference, a suspend
failure, a hang, an out-of-bounds access, a buffer overflow, input
sanitization and other minor fixes.
- dw-dp: An error handling fix
- ethosu: A binary shift overflow fix
- imx: An error handling fix
- logicvc: A dt node reference leak fix
- nouveau: A WARN_ON removal
- samsung-dsim: A memory leak fix
- sharp-memory: A NULL pointer dereference fix
- vmgfx: A reference count and error handling fix
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Maxime Ripard <mripard@redhat.com>
Link: https://patch.msgid.link/20260226-heretic-stimulating-swine-6a2f27@penduick
This commit is contained in:
commit
5e061aac4c
|
|
@ -23,9 +23,9 @@
|
|||
#include "amdxdna_pci_drv.h"
|
||||
#include "amdxdna_pm.h"
|
||||
|
||||
static bool force_cmdlist;
|
||||
static bool force_cmdlist = true;
|
||||
module_param(force_cmdlist, bool, 0600);
|
||||
MODULE_PARM_DESC(force_cmdlist, "Force use command list (Default false)");
|
||||
MODULE_PARM_DESC(force_cmdlist, "Force use command list (Default true)");
|
||||
|
||||
#define HWCTX_MAX_TIMEOUT 60000 /* milliseconds */
|
||||
|
||||
|
|
@ -53,6 +53,7 @@ static void aie2_hwctx_stop(struct amdxdna_dev *xdna, struct amdxdna_hwctx *hwct
|
|||
{
|
||||
drm_sched_stop(&hwctx->priv->sched, bad_job);
|
||||
aie2_destroy_context(xdna->dev_handle, hwctx);
|
||||
drm_sched_start(&hwctx->priv->sched, 0);
|
||||
}
|
||||
|
||||
static int aie2_hwctx_restart(struct amdxdna_dev *xdna, struct amdxdna_hwctx *hwctx)
|
||||
|
|
@ -80,7 +81,6 @@ static int aie2_hwctx_restart(struct amdxdna_dev *xdna, struct amdxdna_hwctx *hw
|
|||
}
|
||||
|
||||
out:
|
||||
drm_sched_start(&hwctx->priv->sched, 0);
|
||||
XDNA_DBG(xdna, "%s restarted, ret %d", hwctx->name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -297,19 +297,23 @@ aie2_sched_job_run(struct drm_sched_job *sched_job)
|
|||
struct dma_fence *fence;
|
||||
int ret;
|
||||
|
||||
if (!hwctx->priv->mbox_chann)
|
||||
ret = amdxdna_pm_resume_get(hwctx->client->xdna);
|
||||
if (ret)
|
||||
return NULL;
|
||||
|
||||
if (!mmget_not_zero(job->mm))
|
||||
if (!hwctx->priv->mbox_chann) {
|
||||
amdxdna_pm_suspend_put(hwctx->client->xdna);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!mmget_not_zero(job->mm)) {
|
||||
amdxdna_pm_suspend_put(hwctx->client->xdna);
|
||||
return ERR_PTR(-ESRCH);
|
||||
}
|
||||
|
||||
kref_get(&job->refcnt);
|
||||
fence = dma_fence_get(job->fence);
|
||||
|
||||
ret = amdxdna_pm_resume_get(hwctx->client->xdna);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (job->drv_cmd) {
|
||||
switch (job->drv_cmd->opcode) {
|
||||
case SYNC_DEBUG_BO:
|
||||
|
|
@ -497,7 +501,7 @@ static void aie2_release_resource(struct amdxdna_hwctx *hwctx)
|
|||
|
||||
if (AIE2_FEATURE_ON(xdna->dev_handle, AIE2_TEMPORAL_ONLY)) {
|
||||
ret = aie2_destroy_context(xdna->dev_handle, hwctx);
|
||||
if (ret)
|
||||
if (ret && ret != -ENODEV)
|
||||
XDNA_ERR(xdna, "Destroy temporal only context failed, ret %d", ret);
|
||||
} else {
|
||||
ret = xrs_release_resource(xdna->xrs_hdl, (uintptr_t)hwctx);
|
||||
|
|
@ -629,7 +633,7 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx)
|
|||
goto free_entity;
|
||||
}
|
||||
|
||||
ret = amdxdna_pm_resume_get(xdna);
|
||||
ret = amdxdna_pm_resume_get_locked(xdna);
|
||||
if (ret)
|
||||
goto free_col_list;
|
||||
|
||||
|
|
@ -760,7 +764,7 @@ static int aie2_hwctx_cu_config(struct amdxdna_hwctx *hwctx, void *buf, u32 size
|
|||
if (!hwctx->cus)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = amdxdna_pm_resume_get(xdna);
|
||||
ret = amdxdna_pm_resume_get_locked(xdna);
|
||||
if (ret)
|
||||
goto free_cus;
|
||||
|
||||
|
|
@ -1070,6 +1074,8 @@ void aie2_hmm_invalidate(struct amdxdna_gem_obj *abo,
|
|||
|
||||
ret = dma_resv_wait_timeout(gobj->resv, DMA_RESV_USAGE_BOOKKEEP,
|
||||
true, MAX_SCHEDULE_TIMEOUT);
|
||||
if (!ret || ret == -ERESTARTSYS)
|
||||
if (!ret)
|
||||
XDNA_ERR(xdna, "Failed to wait for bo, ret %ld", ret);
|
||||
else if (ret == -ERESTARTSYS)
|
||||
XDNA_DBG(xdna, "Wait for bo interrupted by signal");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -216,8 +216,10 @@ static int aie2_destroy_context_req(struct amdxdna_dev_hdl *ndev, u32 id)
|
|||
|
||||
req.context_id = id;
|
||||
ret = aie2_send_mgmt_msg_wait(ndev, &msg);
|
||||
if (ret)
|
||||
if (ret && ret != -ENODEV)
|
||||
XDNA_WARN(xdna, "Destroy context failed, ret %d", ret);
|
||||
else if (ret == -ENODEV)
|
||||
XDNA_DBG(xdna, "Destroy context: device already stopped");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -318,6 +320,9 @@ int aie2_destroy_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwc
|
|||
struct amdxdna_dev *xdna = ndev->xdna;
|
||||
int ret;
|
||||
|
||||
if (!hwctx->priv->mbox_chann)
|
||||
return 0;
|
||||
|
||||
xdna_mailbox_stop_channel(hwctx->priv->mbox_chann);
|
||||
ret = aie2_destroy_context_req(ndev, hwctx->fw_ctx_id);
|
||||
xdna_mailbox_destroy_channel(hwctx->priv->mbox_chann);
|
||||
|
|
@ -694,11 +699,11 @@ aie2_cmdlist_fill_npu_cf(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *siz
|
|||
u32 cmd_len;
|
||||
void *cmd;
|
||||
|
||||
memset(npu_slot, 0, sizeof(*npu_slot));
|
||||
cmd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
|
||||
if (*size < sizeof(*npu_slot) + cmd_len)
|
||||
return -EINVAL;
|
||||
|
||||
memset(npu_slot, 0, sizeof(*npu_slot));
|
||||
npu_slot->cu_idx = amdxdna_cmd_get_cu_idx(cmd_bo);
|
||||
if (npu_slot->cu_idx == INVALID_CU_IDX)
|
||||
return -EINVAL;
|
||||
|
|
@ -719,7 +724,6 @@ aie2_cmdlist_fill_npu_dpu(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *si
|
|||
u32 cmd_len;
|
||||
u32 arg_sz;
|
||||
|
||||
memset(npu_slot, 0, sizeof(*npu_slot));
|
||||
sn = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
|
||||
arg_sz = cmd_len - sizeof(*sn);
|
||||
if (cmd_len < sizeof(*sn) || arg_sz > MAX_NPU_ARGS_SIZE)
|
||||
|
|
@ -728,6 +732,7 @@ aie2_cmdlist_fill_npu_dpu(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *si
|
|||
if (*size < sizeof(*npu_slot) + arg_sz)
|
||||
return -EINVAL;
|
||||
|
||||
memset(npu_slot, 0, sizeof(*npu_slot));
|
||||
npu_slot->cu_idx = amdxdna_cmd_get_cu_idx(cmd_bo);
|
||||
if (npu_slot->cu_idx == INVALID_CU_IDX)
|
||||
return -EINVAL;
|
||||
|
|
@ -751,7 +756,6 @@ aie2_cmdlist_fill_npu_preempt(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t
|
|||
u32 cmd_len;
|
||||
u32 arg_sz;
|
||||
|
||||
memset(npu_slot, 0, sizeof(*npu_slot));
|
||||
pd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
|
||||
arg_sz = cmd_len - sizeof(*pd);
|
||||
if (cmd_len < sizeof(*pd) || arg_sz > MAX_NPU_ARGS_SIZE)
|
||||
|
|
@ -760,6 +764,7 @@ aie2_cmdlist_fill_npu_preempt(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t
|
|||
if (*size < sizeof(*npu_slot) + arg_sz)
|
||||
return -EINVAL;
|
||||
|
||||
memset(npu_slot, 0, sizeof(*npu_slot));
|
||||
npu_slot->cu_idx = amdxdna_cmd_get_cu_idx(cmd_bo);
|
||||
if (npu_slot->cu_idx == INVALID_CU_IDX)
|
||||
return -EINVAL;
|
||||
|
|
@ -787,7 +792,6 @@ aie2_cmdlist_fill_npu_elf(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *si
|
|||
u32 cmd_len;
|
||||
u32 arg_sz;
|
||||
|
||||
memset(npu_slot, 0, sizeof(*npu_slot));
|
||||
pd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
|
||||
arg_sz = cmd_len - sizeof(*pd);
|
||||
if (cmd_len < sizeof(*pd) || arg_sz > MAX_NPU_ARGS_SIZE)
|
||||
|
|
@ -796,6 +800,7 @@ aie2_cmdlist_fill_npu_elf(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *si
|
|||
if (*size < sizeof(*npu_slot) + arg_sz)
|
||||
return -EINVAL;
|
||||
|
||||
memset(npu_slot, 0, sizeof(*npu_slot));
|
||||
npu_slot->type = EXEC_NPU_TYPE_ELF;
|
||||
npu_slot->inst_buf_addr = pd->inst_buf;
|
||||
npu_slot->save_buf_addr = pd->save_buf;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,11 @@ static int aie2_max_col = XRS_MAX_COL;
|
|||
module_param(aie2_max_col, uint, 0600);
|
||||
MODULE_PARM_DESC(aie2_max_col, "Maximum column could be used");
|
||||
|
||||
static char *npu_fw[] = {
|
||||
"npu_7.sbin",
|
||||
"npu.sbin"
|
||||
};
|
||||
|
||||
/*
|
||||
* The management mailbox channel is allocated by firmware.
|
||||
* The related register and ring buffer information is on SRAM BAR.
|
||||
|
|
@ -323,6 +328,7 @@ static void aie2_hw_stop(struct amdxdna_dev *xdna)
|
|||
return;
|
||||
}
|
||||
|
||||
aie2_runtime_cfg(ndev, AIE2_RT_CFG_CLK_GATING, NULL);
|
||||
aie2_mgmt_fw_fini(ndev);
|
||||
xdna_mailbox_stop_channel(ndev->mgmt_chann);
|
||||
xdna_mailbox_destroy_channel(ndev->mgmt_chann);
|
||||
|
|
@ -406,18 +412,18 @@ static int aie2_hw_start(struct amdxdna_dev *xdna)
|
|||
goto stop_psp;
|
||||
}
|
||||
|
||||
ret = aie2_pm_init(ndev);
|
||||
if (ret) {
|
||||
XDNA_ERR(xdna, "failed to init pm, ret %d", ret);
|
||||
goto destroy_mgmt_chann;
|
||||
}
|
||||
|
||||
ret = aie2_mgmt_fw_init(ndev);
|
||||
if (ret) {
|
||||
XDNA_ERR(xdna, "initial mgmt firmware failed, ret %d", ret);
|
||||
goto destroy_mgmt_chann;
|
||||
}
|
||||
|
||||
ret = aie2_pm_init(ndev);
|
||||
if (ret) {
|
||||
XDNA_ERR(xdna, "failed to init pm, ret %d", ret);
|
||||
goto destroy_mgmt_chann;
|
||||
}
|
||||
|
||||
ret = aie2_mgmt_fw_query(ndev);
|
||||
if (ret) {
|
||||
XDNA_ERR(xdna, "failed to query fw, ret %d", ret);
|
||||
|
|
@ -451,7 +457,6 @@ static int aie2_hw_suspend(struct amdxdna_dev *xdna)
|
|||
{
|
||||
struct amdxdna_client *client;
|
||||
|
||||
guard(mutex)(&xdna->dev_lock);
|
||||
list_for_each_entry(client, &xdna->client_list, node)
|
||||
aie2_hwctx_suspend(client);
|
||||
|
||||
|
|
@ -489,6 +494,7 @@ static int aie2_init(struct amdxdna_dev *xdna)
|
|||
struct psp_config psp_conf;
|
||||
const struct firmware *fw;
|
||||
unsigned long bars = 0;
|
||||
char *fw_full_path;
|
||||
int i, nvec, ret;
|
||||
|
||||
if (!hypervisor_is_type(X86_HYPER_NATIVE)) {
|
||||
|
|
@ -503,7 +509,19 @@ static int aie2_init(struct amdxdna_dev *xdna)
|
|||
ndev->priv = xdna->dev_info->dev_priv;
|
||||
ndev->xdna = xdna;
|
||||
|
||||
ret = request_firmware(&fw, ndev->priv->fw_path, &pdev->dev);
|
||||
for (i = 0; i < ARRAY_SIZE(npu_fw); i++) {
|
||||
fw_full_path = kasprintf(GFP_KERNEL, "%s%s", ndev->priv->fw_path, npu_fw[i]);
|
||||
if (!fw_full_path)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = firmware_request_nowarn(&fw, fw_full_path, &pdev->dev);
|
||||
kfree(fw_full_path);
|
||||
if (!ret) {
|
||||
XDNA_INFO(xdna, "Load firmware %s%s", ndev->priv->fw_path, npu_fw[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
XDNA_ERR(xdna, "failed to request_firmware %s, ret %d",
|
||||
ndev->priv->fw_path, ret);
|
||||
|
|
@ -951,7 +969,7 @@ static int aie2_get_info(struct amdxdna_client *client, struct amdxdna_drm_get_i
|
|||
if (!drm_dev_enter(&xdna->ddev, &idx))
|
||||
return -ENODEV;
|
||||
|
||||
ret = amdxdna_pm_resume_get(xdna);
|
||||
ret = amdxdna_pm_resume_get_locked(xdna);
|
||||
if (ret)
|
||||
goto dev_exit;
|
||||
|
||||
|
|
@ -1044,7 +1062,7 @@ static int aie2_get_array(struct amdxdna_client *client,
|
|||
if (!drm_dev_enter(&xdna->ddev, &idx))
|
||||
return -ENODEV;
|
||||
|
||||
ret = amdxdna_pm_resume_get(xdna);
|
||||
ret = amdxdna_pm_resume_get_locked(xdna);
|
||||
if (ret)
|
||||
goto dev_exit;
|
||||
|
||||
|
|
@ -1134,7 +1152,7 @@ static int aie2_set_state(struct amdxdna_client *client,
|
|||
if (!drm_dev_enter(&xdna->ddev, &idx))
|
||||
return -ENODEV;
|
||||
|
||||
ret = amdxdna_pm_resume_get(xdna);
|
||||
ret = amdxdna_pm_resume_get_locked(xdna);
|
||||
if (ret)
|
||||
goto dev_exit;
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ int aie2_pm_set_dpm(struct amdxdna_dev_hdl *ndev, u32 dpm_level)
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = amdxdna_pm_resume_get(ndev->xdna);
|
||||
ret = amdxdna_pm_resume_get_locked(ndev->xdna);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
|||
|
|
@ -104,7 +104,10 @@ void *amdxdna_cmd_get_payload(struct amdxdna_gem_obj *abo, u32 *size)
|
|||
|
||||
if (size) {
|
||||
count = FIELD_GET(AMDXDNA_CMD_COUNT, cmd->header);
|
||||
if (unlikely(count <= num_masks)) {
|
||||
if (unlikely(count <= num_masks ||
|
||||
count * sizeof(u32) +
|
||||
offsetof(struct amdxdna_cmd, data[0]) >
|
||||
abo->mem.size)) {
|
||||
*size = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -266,9 +269,9 @@ int amdxdna_drm_config_hwctx_ioctl(struct drm_device *dev, void *data, struct dr
|
|||
struct amdxdna_drm_config_hwctx *args = data;
|
||||
struct amdxdna_dev *xdna = to_xdna_dev(dev);
|
||||
struct amdxdna_hwctx *hwctx;
|
||||
int ret, idx;
|
||||
u32 buf_size;
|
||||
void *buf;
|
||||
int ret;
|
||||
u64 val;
|
||||
|
||||
if (XDNA_MBZ_DBG(xdna, &args->pad, sizeof(args->pad)))
|
||||
|
|
@ -310,20 +313,17 @@ int amdxdna_drm_config_hwctx_ioctl(struct drm_device *dev, void *data, struct dr
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&xdna->dev_lock);
|
||||
idx = srcu_read_lock(&client->hwctx_srcu);
|
||||
guard(mutex)(&xdna->dev_lock);
|
||||
hwctx = xa_load(&client->hwctx_xa, args->handle);
|
||||
if (!hwctx) {
|
||||
XDNA_DBG(xdna, "PID %d failed to get hwctx %d", client->pid, args->handle);
|
||||
ret = -EINVAL;
|
||||
goto unlock_srcu;
|
||||
goto free_buf;
|
||||
}
|
||||
|
||||
ret = xdna->dev_info->ops->hwctx_config(hwctx, args->param_type, val, buf, buf_size);
|
||||
|
||||
unlock_srcu:
|
||||
srcu_read_unlock(&client->hwctx_srcu, idx);
|
||||
mutex_unlock(&xdna->dev_lock);
|
||||
free_buf:
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -334,7 +334,7 @@ int amdxdna_hwctx_sync_debug_bo(struct amdxdna_client *client, u32 debug_bo_hdl)
|
|||
struct amdxdna_hwctx *hwctx;
|
||||
struct amdxdna_gem_obj *abo;
|
||||
struct drm_gem_object *gobj;
|
||||
int ret, idx;
|
||||
int ret;
|
||||
|
||||
if (!xdna->dev_info->ops->hwctx_sync_debug_bo)
|
||||
return -EOPNOTSUPP;
|
||||
|
|
@ -345,17 +345,15 @@ int amdxdna_hwctx_sync_debug_bo(struct amdxdna_client *client, u32 debug_bo_hdl)
|
|||
|
||||
abo = to_xdna_obj(gobj);
|
||||
guard(mutex)(&xdna->dev_lock);
|
||||
idx = srcu_read_lock(&client->hwctx_srcu);
|
||||
hwctx = xa_load(&client->hwctx_xa, abo->assigned_hwctx);
|
||||
if (!hwctx) {
|
||||
ret = -EINVAL;
|
||||
goto unlock_srcu;
|
||||
goto put_obj;
|
||||
}
|
||||
|
||||
ret = xdna->dev_info->ops->hwctx_sync_debug_bo(hwctx, debug_bo_hdl);
|
||||
|
||||
unlock_srcu:
|
||||
srcu_read_unlock(&client->hwctx_srcu, idx);
|
||||
put_obj:
|
||||
drm_gem_object_put(gobj);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,8 +21,6 @@
|
|||
#include "amdxdna_pci_drv.h"
|
||||
#include "amdxdna_ubuf.h"
|
||||
|
||||
#define XDNA_MAX_CMD_BO_SIZE SZ_32K
|
||||
|
||||
MODULE_IMPORT_NS("DMA_BUF");
|
||||
|
||||
static int
|
||||
|
|
@ -745,12 +743,6 @@ amdxdna_drm_create_cmd_bo(struct drm_device *dev,
|
|||
{
|
||||
struct amdxdna_dev *xdna = to_xdna_dev(dev);
|
||||
struct amdxdna_gem_obj *abo;
|
||||
int ret;
|
||||
|
||||
if (args->size > XDNA_MAX_CMD_BO_SIZE) {
|
||||
XDNA_ERR(xdna, "Command bo size 0x%llx too large", args->size);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (args->size < sizeof(struct amdxdna_cmd)) {
|
||||
XDNA_DBG(xdna, "Command BO size 0x%llx too small", args->size);
|
||||
|
|
@ -764,17 +756,7 @@ amdxdna_drm_create_cmd_bo(struct drm_device *dev,
|
|||
abo->type = AMDXDNA_BO_CMD;
|
||||
abo->client = filp->driver_priv;
|
||||
|
||||
ret = amdxdna_gem_obj_vmap(abo, &abo->mem.kva);
|
||||
if (ret) {
|
||||
XDNA_ERR(xdna, "Vmap cmd bo failed, ret %d", ret);
|
||||
goto release_obj;
|
||||
}
|
||||
|
||||
return abo;
|
||||
|
||||
release_obj:
|
||||
drm_gem_object_put(to_gobj(abo));
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
int amdxdna_drm_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||
|
|
@ -871,6 +853,7 @@ struct amdxdna_gem_obj *amdxdna_gem_get_obj(struct amdxdna_client *client,
|
|||
struct amdxdna_dev *xdna = client->xdna;
|
||||
struct amdxdna_gem_obj *abo;
|
||||
struct drm_gem_object *gobj;
|
||||
int ret;
|
||||
|
||||
gobj = drm_gem_object_lookup(client->filp, bo_hdl);
|
||||
if (!gobj) {
|
||||
|
|
@ -879,9 +862,26 @@ struct amdxdna_gem_obj *amdxdna_gem_get_obj(struct amdxdna_client *client,
|
|||
}
|
||||
|
||||
abo = to_xdna_obj(gobj);
|
||||
if (bo_type == AMDXDNA_BO_INVALID || abo->type == bo_type)
|
||||
if (bo_type != AMDXDNA_BO_INVALID && abo->type != bo_type)
|
||||
goto put_obj;
|
||||
|
||||
if (bo_type != AMDXDNA_BO_CMD || abo->mem.kva)
|
||||
return abo;
|
||||
|
||||
if (abo->mem.size > SZ_32K) {
|
||||
XDNA_ERR(xdna, "Cmd bo is too big %ld", abo->mem.size);
|
||||
goto put_obj;
|
||||
}
|
||||
|
||||
ret = amdxdna_gem_obj_vmap(abo, &abo->mem.kva);
|
||||
if (ret) {
|
||||
XDNA_ERR(xdna, "Vmap cmd bo failed, ret %d", ret);
|
||||
goto put_obj;
|
||||
}
|
||||
|
||||
return abo;
|
||||
|
||||
put_obj:
|
||||
drm_gem_object_put(gobj);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ MODULE_FIRMWARE("amdnpu/1502_00/npu.sbin");
|
|||
MODULE_FIRMWARE("amdnpu/17f0_10/npu.sbin");
|
||||
MODULE_FIRMWARE("amdnpu/17f0_11/npu.sbin");
|
||||
MODULE_FIRMWARE("amdnpu/17f0_20/npu.sbin");
|
||||
MODULE_FIRMWARE("amdnpu/1502_00/npu_7.sbin");
|
||||
MODULE_FIRMWARE("amdnpu/17f0_10/npu_7.sbin");
|
||||
MODULE_FIRMWARE("amdnpu/17f0_11/npu_7.sbin");
|
||||
|
||||
/*
|
||||
* 0.0: Initial version
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ int amdxdna_pm_suspend(struct device *dev)
|
|||
struct amdxdna_dev *xdna = to_xdna_dev(dev_get_drvdata(dev));
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
guard(mutex)(&xdna->dev_lock);
|
||||
if (xdna->dev_info->ops->suspend)
|
||||
ret = xdna->dev_info->ops->suspend(xdna);
|
||||
|
||||
|
|
@ -28,6 +29,7 @@ int amdxdna_pm_resume(struct device *dev)
|
|||
struct amdxdna_dev *xdna = to_xdna_dev(dev_get_drvdata(dev));
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
guard(mutex)(&xdna->dev_lock);
|
||||
if (xdna->dev_info->ops->resume)
|
||||
ret = xdna->dev_info->ops->resume(xdna);
|
||||
|
||||
|
|
|
|||
|
|
@ -15,4 +15,15 @@ void amdxdna_pm_suspend_put(struct amdxdna_dev *xdna);
|
|||
void amdxdna_pm_init(struct amdxdna_dev *xdna);
|
||||
void amdxdna_pm_fini(struct amdxdna_dev *xdna);
|
||||
|
||||
static inline int amdxdna_pm_resume_get_locked(struct amdxdna_dev *xdna)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_unlock(&xdna->dev_lock);
|
||||
ret = amdxdna_pm_resume_get(xdna);
|
||||
mutex_lock(&xdna->dev_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* _AMDXDNA_PM_H_ */
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
|
|
@ -176,7 +177,10 @@ struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev,
|
|||
goto free_ent;
|
||||
}
|
||||
|
||||
exp_info.size += va_ent[i].len;
|
||||
if (check_add_overflow(exp_info.size, va_ent[i].len, &exp_info.size)) {
|
||||
ret = -EINVAL;
|
||||
goto free_ent;
|
||||
}
|
||||
}
|
||||
|
||||
ubuf->nr_pages = exp_info.size >> PAGE_SHIFT;
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ static const struct aie2_fw_feature_tbl npu1_fw_feature_table[] = {
|
|||
};
|
||||
|
||||
static const struct amdxdna_dev_priv npu1_dev_priv = {
|
||||
.fw_path = "amdnpu/1502_00/npu.sbin",
|
||||
.fw_path = "amdnpu/1502_00/",
|
||||
.rt_config = npu1_default_rt_cfg,
|
||||
.dpm_clk_tbl = npu1_dpm_clk_table,
|
||||
.fw_feature_tbl = npu1_fw_feature_table,
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ const struct aie2_fw_feature_tbl npu4_fw_feature_table[] = {
|
|||
};
|
||||
|
||||
static const struct amdxdna_dev_priv npu4_dev_priv = {
|
||||
.fw_path = "amdnpu/17f0_10/npu.sbin",
|
||||
.fw_path = "amdnpu/17f0_10/",
|
||||
.rt_config = npu4_default_rt_cfg,
|
||||
.dpm_clk_tbl = npu4_dpm_clk_table,
|
||||
.fw_feature_tbl = npu4_fw_feature_table,
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@
|
|||
#define NPU5_SRAM_BAR_BASE MMNPU_APERTURE1_BASE
|
||||
|
||||
static const struct amdxdna_dev_priv npu5_dev_priv = {
|
||||
.fw_path = "amdnpu/17f0_11/npu.sbin",
|
||||
.fw_path = "amdnpu/17f0_11/",
|
||||
.rt_config = npu4_default_rt_cfg,
|
||||
.dpm_clk_tbl = npu4_dpm_clk_table,
|
||||
.fw_feature_tbl = npu4_fw_feature_table,
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@
|
|||
#define NPU6_SRAM_BAR_BASE MMNPU_APERTURE1_BASE
|
||||
|
||||
static const struct amdxdna_dev_priv npu6_dev_priv = {
|
||||
.fw_path = "amdnpu/17f0_10/npu.sbin",
|
||||
.fw_path = "amdnpu/17f0_10/",
|
||||
.rt_config = npu4_default_rt_cfg,
|
||||
.dpm_clk_tbl = npu4_dpm_clk_table,
|
||||
.fw_feature_tbl = npu4_fw_feature_table,
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ static void cmd_state_init(struct cmd_state *st)
|
|||
|
||||
static u64 cmd_to_addr(u32 *cmd)
|
||||
{
|
||||
return ((u64)((cmd[0] & 0xff0000) << 16)) | cmd[1];
|
||||
return (((u64)cmd[0] & 0xff0000) << 16) | cmd[1];
|
||||
}
|
||||
|
||||
static u64 dma_length(struct ethosu_validated_cmdstream_info *info,
|
||||
|
|
|
|||
|
|
@ -1881,6 +1881,14 @@ static int samsung_dsim_register_te_irq(struct samsung_dsim *dsi, struct device
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void samsung_dsim_unregister_te_irq(struct samsung_dsim *dsi)
|
||||
{
|
||||
if (dsi->te_gpio) {
|
||||
free_irq(gpiod_to_irq(dsi->te_gpio), dsi);
|
||||
gpiod_put(dsi->te_gpio);
|
||||
}
|
||||
}
|
||||
|
||||
static int samsung_dsim_host_attach(struct mipi_dsi_host *host,
|
||||
struct mipi_dsi_device *device)
|
||||
{
|
||||
|
|
@ -1961,7 +1969,7 @@ static int samsung_dsim_host_attach(struct mipi_dsi_host *host,
|
|||
if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO)) {
|
||||
ret = samsung_dsim_register_te_irq(dsi, &device->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_remove_bridge;
|
||||
}
|
||||
|
||||
// The next bridge can be used by host_ops->attach
|
||||
|
|
@ -1982,15 +1990,12 @@ static int samsung_dsim_host_attach(struct mipi_dsi_host *host,
|
|||
err_release_next_bridge:
|
||||
drm_bridge_put(dsi->bridge.next_bridge);
|
||||
dsi->bridge.next_bridge = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void samsung_dsim_unregister_te_irq(struct samsung_dsim *dsi)
|
||||
{
|
||||
if (dsi->te_gpio) {
|
||||
free_irq(gpiod_to_irq(dsi->te_gpio), dsi);
|
||||
gpiod_put(dsi->te_gpio);
|
||||
}
|
||||
if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO))
|
||||
samsung_dsim_unregister_te_irq(dsi);
|
||||
err_remove_bridge:
|
||||
drm_bridge_remove(&dsi->bridge);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int samsung_dsim_host_detach(struct mipi_dsi_host *host,
|
||||
|
|
|
|||
|
|
@ -2049,7 +2049,9 @@ struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
|
|||
bridge->type = DRM_MODE_CONNECTOR_DisplayPort;
|
||||
bridge->ycbcr_420_allowed = true;
|
||||
|
||||
devm_drm_bridge_add(dev, bridge);
|
||||
ret = devm_drm_bridge_add(dev, bridge);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
dp->aux.dev = dev;
|
||||
dp->aux.drm_dev = encoder->dev;
|
||||
|
|
|
|||
|
|
@ -1415,6 +1415,7 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev,
|
|||
{
|
||||
struct ti_sn65dsi86 *pdata = dev_get_drvdata(adev->dev.parent);
|
||||
struct device_node *np = pdata->dev->of_node;
|
||||
const struct i2c_client *client = to_i2c_client(pdata->dev);
|
||||
int ret;
|
||||
|
||||
pdata->next_bridge = devm_drm_of_get_bridge(&adev->dev, np, 1, 0);
|
||||
|
|
@ -1433,8 +1434,9 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev,
|
|||
? DRM_MODE_CONNECTOR_DisplayPort : DRM_MODE_CONNECTOR_eDP;
|
||||
|
||||
if (pdata->bridge.type == DRM_MODE_CONNECTOR_DisplayPort) {
|
||||
pdata->bridge.ops = DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_DETECT |
|
||||
DRM_BRIDGE_OP_HPD;
|
||||
pdata->bridge.ops = DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_DETECT;
|
||||
if (client->irq)
|
||||
pdata->bridge.ops |= DRM_BRIDGE_OP_HPD;
|
||||
/*
|
||||
* If comms were already enabled they would have been enabled
|
||||
* with the wrong value of HPD_DISABLE. Update it now. Comms
|
||||
|
|
|
|||
|
|
@ -930,7 +930,8 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width,
|
|||
mutex_unlock(&client->modeset_mutex);
|
||||
out:
|
||||
kfree(crtcs);
|
||||
modes_destroy(dev, modes, connector_count);
|
||||
if (modes)
|
||||
modes_destroy(dev, modes, connector_count);
|
||||
kfree(modes);
|
||||
kfree(offsets);
|
||||
kfree(enabled);
|
||||
|
|
|
|||
|
|
@ -1338,14 +1338,14 @@ bool drm_gpusvm_range_pages_valid(struct drm_gpusvm *gpusvm,
|
|||
EXPORT_SYMBOL_GPL(drm_gpusvm_range_pages_valid);
|
||||
|
||||
/**
|
||||
* drm_gpusvm_range_pages_valid_unlocked() - GPU SVM range pages valid unlocked
|
||||
* drm_gpusvm_pages_valid_unlocked() - GPU SVM pages valid unlocked
|
||||
* @gpusvm: Pointer to the GPU SVM structure
|
||||
* @range: Pointer to the GPU SVM range structure
|
||||
* @svm_pages: Pointer to the GPU SVM pages structure
|
||||
*
|
||||
* This function determines if a GPU SVM range pages are valid. Expected be
|
||||
* called without holding gpusvm->notifier_lock.
|
||||
* This function determines if a GPU SVM pages are valid. Expected be called
|
||||
* without holding gpusvm->notifier_lock.
|
||||
*
|
||||
* Return: True if GPU SVM range has valid pages, False otherwise
|
||||
* Return: True if GPU SVM pages are valid, False otherwise
|
||||
*/
|
||||
static bool drm_gpusvm_pages_valid_unlocked(struct drm_gpusvm *gpusvm,
|
||||
struct drm_gpusvm_pages *svm_pages)
|
||||
|
|
|
|||
|
|
@ -256,7 +256,9 @@ static int imx_pd_probe(struct platform_device *pdev)
|
|||
|
||||
platform_set_drvdata(pdev, imxpd);
|
||||
|
||||
devm_drm_bridge_add(dev, &imxpd->bridge);
|
||||
ret = devm_drm_bridge_add(dev, &imxpd->bridge);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return component_add(dev, &imx_pd_ops);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,7 +92,6 @@ static int logicvc_drm_config_parse(struct logicvc_drm *logicvc)
|
|||
struct device *dev = drm_dev->dev;
|
||||
struct device_node *of_node = dev->of_node;
|
||||
struct logicvc_drm_config *config = &logicvc->config;
|
||||
struct device_node *layers_node;
|
||||
int ret;
|
||||
|
||||
logicvc_of_property_parse_bool(of_node, LOGICVC_OF_PROPERTY_DITHERING,
|
||||
|
|
@ -128,7 +127,8 @@ static int logicvc_drm_config_parse(struct logicvc_drm *logicvc)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
layers_node = of_get_child_by_name(of_node, "layers");
|
||||
struct device_node *layers_node __free(device_node) =
|
||||
of_get_child_by_name(of_node, "layers");
|
||||
if (!layers_node) {
|
||||
drm_err(drm_dev, "Missing non-optional layers node\n");
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -737,8 +737,8 @@ r535_gsp_acpi_caps(acpi_handle handle, CAPS_METHOD_DATA *caps)
|
|||
if (!obj)
|
||||
goto done;
|
||||
|
||||
if (WARN_ON(obj->type != ACPI_TYPE_BUFFER) ||
|
||||
WARN_ON(obj->buffer.length != 4))
|
||||
if (obj->type != ACPI_TYPE_BUFFER ||
|
||||
obj->buffer.length != 4)
|
||||
goto done;
|
||||
|
||||
caps->status = 0;
|
||||
|
|
@ -773,8 +773,8 @@ r535_gsp_acpi_jt(acpi_handle handle, JT_METHOD_DATA *jt)
|
|||
if (!obj)
|
||||
goto done;
|
||||
|
||||
if (WARN_ON(obj->type != ACPI_TYPE_BUFFER) ||
|
||||
WARN_ON(obj->buffer.length != 4))
|
||||
if (obj->type != ACPI_TYPE_BUFFER ||
|
||||
obj->buffer.length != 4)
|
||||
goto done;
|
||||
|
||||
jt->status = 0;
|
||||
|
|
@ -861,8 +861,8 @@ r535_gsp_acpi_dod(acpi_handle handle, DOD_METHOD_DATA *dod)
|
|||
|
||||
_DOD = output.pointer;
|
||||
|
||||
if (WARN_ON(_DOD->type != ACPI_TYPE_PACKAGE) ||
|
||||
WARN_ON(_DOD->package.count > ARRAY_SIZE(dod->acpiIdList)))
|
||||
if (_DOD->type != ACPI_TYPE_PACKAGE ||
|
||||
_DOD->package.count > ARRAY_SIZE(dod->acpiIdList))
|
||||
return;
|
||||
|
||||
for (int i = 0; i < _DOD->package.count; i++) {
|
||||
|
|
|
|||
|
|
@ -541,8 +541,8 @@ static int sharp_memory_probe(struct spi_device *spi)
|
|||
|
||||
smd = devm_drm_dev_alloc(dev, &sharp_memory_drm_driver,
|
||||
struct sharp_memory_device, drm);
|
||||
if (!smd)
|
||||
return -ENOMEM;
|
||||
if (IS_ERR(smd))
|
||||
return PTR_ERR(smd);
|
||||
|
||||
spi_set_drvdata(spi, smd);
|
||||
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ struct vmw_cmdbuf_context {
|
|||
* @handle: DMA address handle for the command buffer space if @using_mob is
|
||||
* false. Immutable.
|
||||
* @size: The size of the command buffer space. Immutable.
|
||||
* @id: Monotonically increasing ID of the last cmdbuf submitted.
|
||||
* @num_contexts: Number of contexts actually enabled.
|
||||
*/
|
||||
struct vmw_cmdbuf_man {
|
||||
|
|
@ -132,6 +133,7 @@ struct vmw_cmdbuf_man {
|
|||
bool has_pool;
|
||||
dma_addr_t handle;
|
||||
size_t size;
|
||||
u64 id;
|
||||
u32 num_contexts;
|
||||
};
|
||||
|
||||
|
|
@ -303,6 +305,8 @@ static int vmw_cmdbuf_header_submit(struct vmw_cmdbuf_header *header)
|
|||
struct vmw_cmdbuf_man *man = header->man;
|
||||
u32 val;
|
||||
|
||||
header->cb_header->id = man->id++;
|
||||
|
||||
val = upper_32_bits(header->handle);
|
||||
vmw_write(man->dev_priv, SVGA_REG_COMMAND_HIGH, val);
|
||||
|
||||
|
|
|
|||
|
|
@ -1143,7 +1143,7 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv,
|
|||
ret = vmw_user_bo_lookup(sw_context->filp, handle, &vmw_bo);
|
||||
if (ret != 0) {
|
||||
drm_dbg(&dev_priv->drm, "Could not find or use MOB buffer.\n");
|
||||
return PTR_ERR(vmw_bo);
|
||||
return ret;
|
||||
}
|
||||
vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_MOB, VMW_BO_DOMAIN_MOB);
|
||||
ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo);
|
||||
|
|
@ -1199,7 +1199,7 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
|
|||
ret = vmw_user_bo_lookup(sw_context->filp, handle, &vmw_bo);
|
||||
if (ret != 0) {
|
||||
drm_dbg(&dev_priv->drm, "Could not find or use GMR region.\n");
|
||||
return PTR_ERR(vmw_bo);
|
||||
return ret;
|
||||
}
|
||||
vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM,
|
||||
VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM);
|
||||
|
|
|
|||
|
|
@ -260,6 +260,13 @@ int vmw_bo_dirty_add(struct vmw_bo *vbo)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void vmw_bo_dirty_free(struct kref *kref)
|
||||
{
|
||||
struct vmw_bo_dirty *dirty = container_of(kref, struct vmw_bo_dirty, ref_count);
|
||||
|
||||
kvfree(dirty);
|
||||
}
|
||||
|
||||
/**
|
||||
* vmw_bo_dirty_release - Release a dirty-tracking user from a buffer object
|
||||
* @vbo: The buffer object
|
||||
|
|
@ -274,7 +281,7 @@ void vmw_bo_dirty_release(struct vmw_bo *vbo)
|
|||
{
|
||||
struct vmw_bo_dirty *dirty = vbo->dirty;
|
||||
|
||||
if (dirty && kref_put(&dirty->ref_count, (void *)kvfree))
|
||||
if (dirty && kref_put(&dirty->ref_count, vmw_bo_dirty_free))
|
||||
vbo->dirty = NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -401,8 +401,8 @@ extern "C" {
|
|||
* implementation can multiply the values by 2^6=64. For that reason the padding
|
||||
* must only contain zeros.
|
||||
* index 0 = Y plane, [15:0] z:Y [6:10] little endian
|
||||
* index 1 = Cr plane, [15:0] z:Cr [6:10] little endian
|
||||
* index 2 = Cb plane, [15:0] z:Cb [6:10] little endian
|
||||
* index 1 = Cb plane, [15:0] z:Cb [6:10] little endian
|
||||
* index 2 = Cr plane, [15:0] z:Cr [6:10] little endian
|
||||
*/
|
||||
#define DRM_FORMAT_S010 fourcc_code('S', '0', '1', '0') /* 2x2 subsampled Cb (1) and Cr (2) planes 10 bits per channel */
|
||||
#define DRM_FORMAT_S210 fourcc_code('S', '2', '1', '0') /* 2x1 subsampled Cb (1) and Cr (2) planes 10 bits per channel */
|
||||
|
|
@ -414,8 +414,8 @@ extern "C" {
|
|||
* implementation can multiply the values by 2^4=16. For that reason the padding
|
||||
* must only contain zeros.
|
||||
* index 0 = Y plane, [15:0] z:Y [4:12] little endian
|
||||
* index 1 = Cr plane, [15:0] z:Cr [4:12] little endian
|
||||
* index 2 = Cb plane, [15:0] z:Cb [4:12] little endian
|
||||
* index 1 = Cb plane, [15:0] z:Cb [4:12] little endian
|
||||
* index 2 = Cr plane, [15:0] z:Cr [4:12] little endian
|
||||
*/
|
||||
#define DRM_FORMAT_S012 fourcc_code('S', '0', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes 12 bits per channel */
|
||||
#define DRM_FORMAT_S212 fourcc_code('S', '2', '1', '2') /* 2x1 subsampled Cb (1) and Cr (2) planes 12 bits per channel */
|
||||
|
|
@ -424,8 +424,8 @@ extern "C" {
|
|||
/*
|
||||
* 3 plane YCbCr
|
||||
* index 0 = Y plane, [15:0] Y little endian
|
||||
* index 1 = Cr plane, [15:0] Cr little endian
|
||||
* index 2 = Cb plane, [15:0] Cb little endian
|
||||
* index 1 = Cb plane, [15:0] Cb little endian
|
||||
* index 2 = Cr plane, [15:0] Cr little endian
|
||||
*/
|
||||
#define DRM_FORMAT_S016 fourcc_code('S', '0', '1', '6') /* 2x2 subsampled Cb (1) and Cr (2) planes 16 bits per channel */
|
||||
#define DRM_FORMAT_S216 fourcc_code('S', '2', '1', '6') /* 2x1 subsampled Cb (1) and Cr (2) planes 16 bits per channel */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user