mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-16 17:57:38 -04:00
Merge tag 'drm-misc-next-2025-09-11' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next
drm-misc-next for v6.18: UAPI Changes: - Provide 'boot_display' attribute on boot-up devices amdxdma: - Add ioctl DRM_IOCTL_AMDXDNA_GET_ARRAY Cross-subsystem Changes: bindings: - Add Mayqueen vendor prefix mayqueen- pci: - vgaarb: Use screen_info helpers Core Changes: ttm: - Add interface to populate buffers Driver Changes: amdgpu: - Pre-populate exported buffers ast: - Clean up detection of DRAM config bochs: - Clean up bridge: - adv7511: Write full Audio infoframe - ite6263: Support vendor-specific infoframes - simple: Add support for Realtek RTD2171 DP-to-HDMI plus DT bindings - Clean up gma500: - Clean up nouveau: - Pre-populate exported buffers panel: - edp: Add support for additonal mt8189 Chromebook panels - lvds: Add DT bindings for EDT ETML0700Z8DHA - Clean up pixpaper: - Add support for Mayqueen Pixpaper plus DT bindings rcar-du: - Use RUNTIME_PM_OPS - Add support for DSI commands vkms: - Support variants of ARGB8888, ARGB16161616, RGB565, RGB888 and P01x - Spport YUV with 16-bit components xe: - Pre-populate exported buffers Signed-off-by: Dave Airlie <airlied@redhat.com> From: Thomas Zimmermann <tzimmermann@suse.de> Link: https://lore.kernel.org/r/20250911091737.GA39831@linux.fritz.box
This commit is contained in:
8
Documentation/ABI/testing/sysfs-class-drm
Normal file
8
Documentation/ABI/testing/sysfs-class-drm
Normal file
@@ -0,0 +1,8 @@
|
||||
What: /sys/class/drm/.../boot_display
|
||||
Date: January 2026
|
||||
Contact: Linux DRI developers <dri-devel@vger.kernel.org>
|
||||
Description:
|
||||
This file indicates that displays connected to the device were
|
||||
used to display the boot sequence. If a display connected to
|
||||
the device was used to display the boot sequence the file will
|
||||
be present and contain "1".
|
||||
@@ -29,6 +29,7 @@ properties:
|
||||
- adi,adv7123
|
||||
- dumb-vga-dac
|
||||
- radxa,ra620
|
||||
- realtek,rtd2171
|
||||
- ti,opa362
|
||||
- ti,ths8134
|
||||
- ti,ths8135
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/mayqueen,pixpaper.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Mayqueen Pixpaper e-ink display panel
|
||||
|
||||
maintainers:
|
||||
- LiangCheng Wang <zaq14760@gmail.com>
|
||||
|
||||
description:
|
||||
The Pixpaper is an e-ink display panel controlled via an SPI interface.
|
||||
The panel has a resolution of 122x250 pixels and requires GPIO pins for
|
||||
reset, busy, and data/command control.
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: mayqueen,pixpaper
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
spi-max-frequency:
|
||||
maximum: 1000000
|
||||
default: 1000000
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
busy-gpios:
|
||||
maxItems: 1
|
||||
|
||||
dc-gpios:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reset-gpios
|
||||
- busy-gpios
|
||||
- dc-gpios
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
display@0 {
|
||||
compatible = "mayqueen,pixpaper";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <1000000>;
|
||||
reset-gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>;
|
||||
busy-gpios = <&gpio1 18 GPIO_ACTIVE_HIGH>;
|
||||
dc-gpios = <&gpio1 19 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
@@ -48,6 +48,8 @@ properties:
|
||||
- auo,g084sn05
|
||||
# Chunghwa Picture Tubes Ltd. 7" WXGA (800x1280) TFT LCD LVDS panel
|
||||
- chunghwa,claa070wp03xg
|
||||
# EDT ETML0700Z8DHA 7.0" Full HD (1920x1080) color TFT LCD LVDS panel
|
||||
- edt,etml0700z8dha
|
||||
# EDT ETML0700Z9NDHA 7.0" WSVGA (1024x600) color TFT LCD LVDS panel
|
||||
- edt,etml0700z9ndha
|
||||
# HannStar Display Corp. HSD101PWW2 10.1" WXGA (1280x800) LVDS panel
|
||||
|
||||
@@ -933,6 +933,8 @@ patternProperties:
|
||||
description: Maxim Integrated Products
|
||||
"^maxlinear,.*":
|
||||
description: MaxLinear Inc.
|
||||
"^mayqueen,.*":
|
||||
description: Mayqueen Technologies Ltd.
|
||||
"^mbvl,.*":
|
||||
description: Mobiveil Inc.
|
||||
"^mcube,.*":
|
||||
|
||||
10
MAINTAINERS
10
MAINTAINERS
@@ -1243,7 +1243,7 @@ F: drivers/spi/spi-amd.c
|
||||
F: drivers/spi/spi-amd.h
|
||||
|
||||
AMD XDNA DRIVER
|
||||
M: Min Ma <min.ma@amd.com>
|
||||
M: Min Ma <mamin506@gmail.com>
|
||||
M: Lizhi Hou <lizhi.hou@amd.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Supported
|
||||
@@ -7490,7 +7490,6 @@ F: drivers/soc/ti/smartreflex.c
|
||||
F: include/linux/power/smartreflex.h
|
||||
|
||||
DRM ACCEL DRIVERS FOR INTEL VPU
|
||||
M: Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
|
||||
M: Maciej Falkowski <maciej.falkowski@linux.intel.com>
|
||||
M: Karol Wachowski <karol.wachowski@linux.intel.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
@@ -7877,6 +7876,13 @@ T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/display/repaper.txt
|
||||
F: drivers/gpu/drm/tiny/repaper.c
|
||||
|
||||
DRM DRIVER FOR PIXPAPER E-INK PANEL
|
||||
M: LiangCheng Wang <zaq14760@gmail.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/display/mayqueen,pixpaper.yaml
|
||||
F: drivers/gpu/drm/tiny/pixpaper.c
|
||||
|
||||
DRM DRIVER FOR QEMU'S CIRRUS DEVICE
|
||||
M: Dave Airlie <airlied@redhat.com>
|
||||
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
struct device;
|
||||
|
||||
#if defined(CONFIG_STI_CORE)
|
||||
#if defined(CONFIG_STI_CORE) && defined(CONFIG_VIDEO)
|
||||
bool video_is_primary_device(struct device *dev);
|
||||
#define video_is_primary_device video_is_primary_device
|
||||
#endif
|
||||
|
||||
@@ -19,8 +19,10 @@ static inline pgprot_t pgprot_framebuffer(pgprot_t prot,
|
||||
#define pgprot_framebuffer pgprot_framebuffer
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_VIDEO
|
||||
bool video_is_primary_device(struct device *dev);
|
||||
#define video_is_primary_device video_is_primary_device
|
||||
#endif
|
||||
|
||||
static inline void fb_memcpy_fromio(void *to, const volatile void __iomem *from, size_t n)
|
||||
{
|
||||
|
||||
@@ -13,8 +13,10 @@ pgprot_t pgprot_framebuffer(pgprot_t prot,
|
||||
unsigned long offset);
|
||||
#define pgprot_framebuffer pgprot_framebuffer
|
||||
|
||||
#ifdef CONFIG_VIDEO
|
||||
bool video_is_primary_device(struct device *dev);
|
||||
#define video_is_primary_device video_is_primary_device
|
||||
#endif
|
||||
|
||||
#include <asm-generic/video.h>
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/screen_info.h>
|
||||
#include <linux/vgaarb.h>
|
||||
|
||||
#include <asm/video.h>
|
||||
@@ -27,6 +28,11 @@ EXPORT_SYMBOL(pgprot_framebuffer);
|
||||
|
||||
bool video_is_primary_device(struct device *dev)
|
||||
{
|
||||
#ifdef CONFIG_SCREEN_INFO
|
||||
struct screen_info *si = &screen_info;
|
||||
struct resource res[SCREEN_INFO_MAX_RESOURCES];
|
||||
ssize_t i, numres;
|
||||
#endif
|
||||
struct pci_dev *pdev;
|
||||
|
||||
if (!dev_is_pci(dev))
|
||||
@@ -34,7 +40,24 @@ bool video_is_primary_device(struct device *dev)
|
||||
|
||||
pdev = to_pci_dev(dev);
|
||||
|
||||
return (pdev == vga_default_device());
|
||||
if (!pci_is_display(pdev))
|
||||
return false;
|
||||
|
||||
if (pdev == vga_default_device())
|
||||
return true;
|
||||
|
||||
#ifdef CONFIG_SCREEN_INFO
|
||||
numres = screen_info_resources(si, res, ARRAY_SIZE(res));
|
||||
for (i = 0; i < numres; ++i) {
|
||||
if (!(res[i].flags & IORESOURCE_MEM))
|
||||
continue;
|
||||
|
||||
if (pci_find_resource(pdev, &res[i]))
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL(video_is_primary_device);
|
||||
|
||||
|
||||
@@ -785,11 +785,12 @@ static int aie2_get_clock_metadata(struct amdxdna_client *client,
|
||||
|
||||
static int aie2_hwctx_status_cb(struct amdxdna_hwctx *hwctx, void *arg)
|
||||
{
|
||||
struct amdxdna_drm_query_hwctx *tmp __free(kfree) = NULL;
|
||||
struct amdxdna_drm_get_info *get_info_args = arg;
|
||||
struct amdxdna_drm_query_hwctx __user *buf;
|
||||
struct amdxdna_drm_hwctx_entry *tmp __free(kfree) = NULL;
|
||||
struct amdxdna_drm_get_array *array_args = arg;
|
||||
struct amdxdna_drm_hwctx_entry __user *buf;
|
||||
u32 size;
|
||||
|
||||
if (get_info_args->buffer_size < sizeof(*tmp))
|
||||
if (!array_args->num_element)
|
||||
return -EINVAL;
|
||||
|
||||
tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
|
||||
@@ -802,14 +803,23 @@ static int aie2_hwctx_status_cb(struct amdxdna_hwctx *hwctx, void *arg)
|
||||
tmp->num_col = hwctx->num_col;
|
||||
tmp->command_submissions = hwctx->priv->seq;
|
||||
tmp->command_completions = hwctx->priv->completed;
|
||||
tmp->pasid = hwctx->client->pasid;
|
||||
tmp->priority = hwctx->qos.priority;
|
||||
tmp->gops = hwctx->qos.gops;
|
||||
tmp->fps = hwctx->qos.fps;
|
||||
tmp->dma_bandwidth = hwctx->qos.dma_bandwidth;
|
||||
tmp->latency = hwctx->qos.latency;
|
||||
tmp->frame_exec_time = hwctx->qos.frame_exec_time;
|
||||
tmp->state = AMDXDNA_HWCTX_STATE_ACTIVE;
|
||||
|
||||
buf = u64_to_user_ptr(get_info_args->buffer);
|
||||
buf = u64_to_user_ptr(array_args->buffer);
|
||||
size = min(sizeof(*tmp), array_args->element_size);
|
||||
|
||||
if (copy_to_user(buf, tmp, sizeof(*tmp)))
|
||||
if (copy_to_user(buf, tmp, size))
|
||||
return -EFAULT;
|
||||
|
||||
get_info_args->buffer += sizeof(*tmp);
|
||||
get_info_args->buffer_size -= sizeof(*tmp);
|
||||
array_args->buffer += size;
|
||||
array_args->num_element--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -817,23 +827,24 @@ static int aie2_hwctx_status_cb(struct amdxdna_hwctx *hwctx, void *arg)
|
||||
static int aie2_get_hwctx_status(struct amdxdna_client *client,
|
||||
struct amdxdna_drm_get_info *args)
|
||||
{
|
||||
struct amdxdna_drm_get_array array_args;
|
||||
struct amdxdna_dev *xdna = client->xdna;
|
||||
struct amdxdna_drm_get_info info_args;
|
||||
struct amdxdna_client *tmp_client;
|
||||
int ret;
|
||||
|
||||
drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
|
||||
|
||||
info_args.buffer = args->buffer;
|
||||
info_args.buffer_size = args->buffer_size;
|
||||
|
||||
array_args.element_size = sizeof(struct amdxdna_drm_query_hwctx);
|
||||
array_args.buffer = args->buffer;
|
||||
array_args.num_element = args->buffer_size / array_args.element_size;
|
||||
list_for_each_entry(tmp_client, &xdna->client_list, node) {
|
||||
ret = amdxdna_hwctx_walk(tmp_client, &info_args, aie2_hwctx_status_cb);
|
||||
ret = amdxdna_hwctx_walk(tmp_client, &array_args,
|
||||
aie2_hwctx_status_cb);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
args->buffer_size = (u32)(info_args.buffer - args->buffer);
|
||||
args->buffer_size -= (u32)(array_args.buffer - args->buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -877,6 +888,58 @@ static int aie2_get_info(struct amdxdna_client *client, struct amdxdna_drm_get_i
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int aie2_query_ctx_status_array(struct amdxdna_client *client,
|
||||
struct amdxdna_drm_get_array *args)
|
||||
{
|
||||
struct amdxdna_drm_get_array array_args;
|
||||
struct amdxdna_dev *xdna = client->xdna;
|
||||
struct amdxdna_client *tmp_client;
|
||||
int ret;
|
||||
|
||||
drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
|
||||
|
||||
array_args.element_size = min(args->element_size,
|
||||
sizeof(struct amdxdna_drm_hwctx_entry));
|
||||
array_args.buffer = args->buffer;
|
||||
array_args.num_element = args->num_element * args->element_size /
|
||||
array_args.element_size;
|
||||
list_for_each_entry(tmp_client, &xdna->client_list, node) {
|
||||
ret = amdxdna_hwctx_walk(tmp_client, &array_args,
|
||||
aie2_hwctx_status_cb);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
args->element_size = array_args.element_size;
|
||||
args->num_element = (u32)((array_args.buffer - args->buffer) /
|
||||
args->element_size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int aie2_get_array(struct amdxdna_client *client,
|
||||
struct amdxdna_drm_get_array *args)
|
||||
{
|
||||
struct amdxdna_dev *xdna = client->xdna;
|
||||
int ret, idx;
|
||||
|
||||
if (!drm_dev_enter(&xdna->ddev, &idx))
|
||||
return -ENODEV;
|
||||
|
||||
switch (args->param) {
|
||||
case DRM_AMDXDNA_HW_CONTEXT_ALL:
|
||||
ret = aie2_query_ctx_status_array(client, args);
|
||||
break;
|
||||
default:
|
||||
XDNA_ERR(xdna, "Not supported request parameter %u", args->param);
|
||||
ret = -EOPNOTSUPP;
|
||||
}
|
||||
XDNA_DBG(xdna, "Got param %d", args->param);
|
||||
|
||||
drm_dev_exit(idx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int aie2_set_power_mode(struct amdxdna_client *client,
|
||||
struct amdxdna_drm_set_state *args)
|
||||
{
|
||||
@@ -926,15 +989,16 @@ static int aie2_set_state(struct amdxdna_client *client,
|
||||
}
|
||||
|
||||
const struct amdxdna_dev_ops aie2_ops = {
|
||||
.init = aie2_init,
|
||||
.fini = aie2_fini,
|
||||
.resume = aie2_hw_resume,
|
||||
.suspend = aie2_hw_suspend,
|
||||
.get_aie_info = aie2_get_info,
|
||||
.set_aie_state = aie2_set_state,
|
||||
.hwctx_init = aie2_hwctx_init,
|
||||
.hwctx_fini = aie2_hwctx_fini,
|
||||
.hwctx_config = aie2_hwctx_config,
|
||||
.cmd_submit = aie2_cmd_submit,
|
||||
.init = aie2_init,
|
||||
.fini = aie2_fini,
|
||||
.resume = aie2_hw_resume,
|
||||
.suspend = aie2_hw_suspend,
|
||||
.get_aie_info = aie2_get_info,
|
||||
.set_aie_state = aie2_set_state,
|
||||
.hwctx_init = aie2_hwctx_init,
|
||||
.hwctx_fini = aie2_hwctx_fini,
|
||||
.hwctx_config = aie2_hwctx_config,
|
||||
.cmd_submit = aie2_cmd_submit,
|
||||
.hmm_invalidate = aie2_hmm_invalidate,
|
||||
.get_array = aie2_get_array,
|
||||
};
|
||||
|
||||
@@ -26,6 +26,13 @@ MODULE_FIRMWARE("amdnpu/17f0_10/npu.sbin");
|
||||
MODULE_FIRMWARE("amdnpu/17f0_11/npu.sbin");
|
||||
MODULE_FIRMWARE("amdnpu/17f0_20/npu.sbin");
|
||||
|
||||
/*
|
||||
* 0.0: Initial version
|
||||
* 0.1: Support getting all hardware contexts by DRM_IOCTL_AMDXDNA_GET_ARRAY
|
||||
*/
|
||||
#define AMDXDNA_DRIVER_MAJOR 0
|
||||
#define AMDXDNA_DRIVER_MINOR 1
|
||||
|
||||
/*
|
||||
* Bind the driver base on (vendor_id, device_id) pair and later use the
|
||||
* (device_id, rev_id) pair as a key to select the devices. The devices with
|
||||
@@ -164,6 +171,23 @@ static int amdxdna_drm_get_info_ioctl(struct drm_device *dev, void *data, struct
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int amdxdna_drm_get_array_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *filp)
|
||||
{
|
||||
struct amdxdna_client *client = filp->driver_priv;
|
||||
struct amdxdna_dev *xdna = to_xdna_dev(dev);
|
||||
struct amdxdna_drm_get_array *args = data;
|
||||
|
||||
if (!xdna->dev_info->ops->get_array)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (args->pad || !args->num_element || !args->element_size)
|
||||
return -EINVAL;
|
||||
|
||||
guard(mutex)(&xdna->dev_lock);
|
||||
return xdna->dev_info->ops->get_array(client, args);
|
||||
}
|
||||
|
||||
static int amdxdna_drm_set_state_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||
{
|
||||
struct amdxdna_client *client = filp->driver_priv;
|
||||
@@ -195,6 +219,7 @@ static const struct drm_ioctl_desc amdxdna_drm_ioctls[] = {
|
||||
DRM_IOCTL_DEF_DRV(AMDXDNA_EXEC_CMD, amdxdna_drm_submit_cmd_ioctl, 0),
|
||||
/* AIE hardware */
|
||||
DRM_IOCTL_DEF_DRV(AMDXDNA_GET_INFO, amdxdna_drm_get_info_ioctl, 0),
|
||||
DRM_IOCTL_DEF_DRV(AMDXDNA_GET_ARRAY, amdxdna_drm_get_array_ioctl, 0),
|
||||
DRM_IOCTL_DEF_DRV(AMDXDNA_SET_STATE, amdxdna_drm_set_state_ioctl, DRM_ROOT_ONLY),
|
||||
};
|
||||
|
||||
@@ -218,6 +243,8 @@ const struct drm_driver amdxdna_drm_drv = {
|
||||
.fops = &amdxdna_fops,
|
||||
.name = "amdxdna_accel_driver",
|
||||
.desc = "AMD XDNA DRM implementation",
|
||||
.major = AMDXDNA_DRIVER_MAJOR,
|
||||
.minor = AMDXDNA_DRIVER_MINOR,
|
||||
.open = amdxdna_drm_open,
|
||||
.postclose = amdxdna_drm_close,
|
||||
.ioctls = amdxdna_drm_ioctls,
|
||||
|
||||
@@ -58,6 +58,7 @@ struct amdxdna_dev_ops {
|
||||
int (*cmd_submit)(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job, u64 *seq);
|
||||
int (*get_aie_info)(struct amdxdna_client *client, struct amdxdna_drm_get_info *args);
|
||||
int (*set_aie_state)(struct amdxdna_client *client, struct amdxdna_drm_set_state *args);
|
||||
int (*get_array)(struct amdxdna_client *client, struct amdxdna_drm_get_array *args);
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -313,11 +313,23 @@ struct dma_buf *amdgpu_gem_prime_export(struct drm_gem_object *gobj,
|
||||
{
|
||||
struct amdgpu_bo *bo = gem_to_amdgpu_bo(gobj);
|
||||
struct dma_buf *buf;
|
||||
struct ttm_operation_ctx ctx = {
|
||||
.interruptible = true,
|
||||
.no_wait_gpu = true,
|
||||
/* We opt to avoid OOM on system pages allocations */
|
||||
.gfp_retry_mayfail = true,
|
||||
.allow_res_evict = false,
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) ||
|
||||
bo->flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID)
|
||||
return ERR_PTR(-EPERM);
|
||||
|
||||
ret = ttm_bo_setup_export(&bo->tbo, &ctx);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
buf = drm_gem_prime_export(gobj, flags);
|
||||
if (!IS_ERR(buf))
|
||||
buf->ops = &amdgpu_dmabuf_ops;
|
||||
|
||||
@@ -31,6 +31,39 @@
|
||||
#include "ast_drv.h"
|
||||
#include "ast_post.h"
|
||||
|
||||
/*
|
||||
* DRAM type
|
||||
*/
|
||||
|
||||
static enum ast_dram_layout ast_2100_get_dram_layout_p2a(struct ast_device *ast)
|
||||
{
|
||||
u32 mcr_cfg;
|
||||
enum ast_dram_layout dram_layout;
|
||||
|
||||
ast_write32(ast, 0xf004, 0x1e6e0000);
|
||||
ast_write32(ast, 0xf000, 0x1);
|
||||
mcr_cfg = ast_read32(ast, 0x10004);
|
||||
|
||||
switch (mcr_cfg & 0x0c) {
|
||||
case 0:
|
||||
case 4:
|
||||
default:
|
||||
dram_layout = AST_DRAM_512Mx16;
|
||||
break;
|
||||
case 8:
|
||||
if (mcr_cfg & 0x40)
|
||||
dram_layout = AST_DRAM_1Gx16;
|
||||
else
|
||||
dram_layout = AST_DRAM_512Mx32;
|
||||
break;
|
||||
case 0xc:
|
||||
dram_layout = AST_DRAM_1Gx32;
|
||||
break;
|
||||
}
|
||||
|
||||
return dram_layout;
|
||||
}
|
||||
|
||||
/*
|
||||
* POST
|
||||
*/
|
||||
@@ -266,6 +299,7 @@ static void ast_post_chip_2100(struct ast_device *ast)
|
||||
u8 j;
|
||||
u32 data, temp, i;
|
||||
const struct ast_dramstruct *dram_reg_info;
|
||||
enum ast_dram_layout dram_layout = ast_2100_get_dram_layout_p2a(ast);
|
||||
|
||||
j = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff);
|
||||
|
||||
@@ -292,11 +326,17 @@ static void ast_post_chip_2100(struct ast_device *ast)
|
||||
for (i = 0; i < 15; i++)
|
||||
udelay(dram_reg_info->data);
|
||||
} else if (AST_DRAMSTRUCT_IS(dram_reg_info, DRAM_TYPE)) {
|
||||
data = dram_reg_info->data;
|
||||
if (ast->dram_type == AST_DRAM_1Gx16)
|
||||
switch (dram_layout) {
|
||||
case AST_DRAM_1Gx16:
|
||||
data = 0x00000d89;
|
||||
else if (ast->dram_type == AST_DRAM_1Gx32)
|
||||
break;
|
||||
case AST_DRAM_1Gx32:
|
||||
data = 0x00000c8d;
|
||||
break;
|
||||
default:
|
||||
data = dram_reg_info->data;
|
||||
break;
|
||||
}
|
||||
|
||||
temp = ast_read32(ast, 0x12070);
|
||||
temp &= 0xc;
|
||||
|
||||
@@ -98,13 +98,15 @@ enum ast_config_mode {
|
||||
ast_use_defaults
|
||||
};
|
||||
|
||||
#define AST_DRAM_512Mx16 0
|
||||
#define AST_DRAM_1Gx16 1
|
||||
#define AST_DRAM_512Mx32 2
|
||||
#define AST_DRAM_1Gx32 3
|
||||
#define AST_DRAM_2Gx16 6
|
||||
#define AST_DRAM_4Gx16 7
|
||||
#define AST_DRAM_8Gx16 8
|
||||
enum ast_dram_layout {
|
||||
AST_DRAM_512Mx16 = 0,
|
||||
AST_DRAM_1Gx16 = 1,
|
||||
AST_DRAM_512Mx32 = 2,
|
||||
AST_DRAM_1Gx32 = 3,
|
||||
AST_DRAM_2Gx16 = 6,
|
||||
AST_DRAM_4Gx16 = 7,
|
||||
AST_DRAM_8Gx16 = 8,
|
||||
};
|
||||
|
||||
/*
|
||||
* Hardware cursor
|
||||
@@ -172,10 +174,6 @@ struct ast_device {
|
||||
enum ast_config_mode config_mode;
|
||||
enum ast_chip chip;
|
||||
|
||||
uint32_t dram_bus_width;
|
||||
uint32_t dram_type;
|
||||
uint32_t mclk;
|
||||
|
||||
void __iomem *vram;
|
||||
unsigned long vram_base;
|
||||
unsigned long vram_size;
|
||||
|
||||
@@ -210,126 +210,6 @@ static void ast_detect_tx_chip(struct ast_device *ast, bool need_post)
|
||||
drm_info(dev, "Using %s\n", info_str[ast->tx_chip]);
|
||||
}
|
||||
|
||||
static int ast_get_dram_info(struct ast_device *ast)
|
||||
{
|
||||
struct drm_device *dev = &ast->base;
|
||||
struct device_node *np = dev->dev->of_node;
|
||||
uint32_t mcr_cfg, mcr_scu_mpll, mcr_scu_strap;
|
||||
uint32_t denum, num, div, ref_pll, dsel;
|
||||
|
||||
switch (ast->config_mode) {
|
||||
case ast_use_dt:
|
||||
/*
|
||||
* If some properties are missing, use reasonable
|
||||
* defaults for GEN5
|
||||
*/
|
||||
if (of_property_read_u32(np, "aspeed,mcr-configuration",
|
||||
&mcr_cfg))
|
||||
mcr_cfg = 0x00000577;
|
||||
if (of_property_read_u32(np, "aspeed,mcr-scu-mpll",
|
||||
&mcr_scu_mpll))
|
||||
mcr_scu_mpll = 0x000050C0;
|
||||
if (of_property_read_u32(np, "aspeed,mcr-scu-strap",
|
||||
&mcr_scu_strap))
|
||||
mcr_scu_strap = 0;
|
||||
break;
|
||||
case ast_use_p2a:
|
||||
ast_write32(ast, 0xf004, 0x1e6e0000);
|
||||
ast_write32(ast, 0xf000, 0x1);
|
||||
mcr_cfg = ast_read32(ast, 0x10004);
|
||||
mcr_scu_mpll = ast_read32(ast, 0x10120);
|
||||
mcr_scu_strap = ast_read32(ast, 0x10170);
|
||||
break;
|
||||
case ast_use_defaults:
|
||||
default:
|
||||
ast->dram_bus_width = 16;
|
||||
ast->dram_type = AST_DRAM_1Gx16;
|
||||
if (IS_AST_GEN6(ast))
|
||||
ast->mclk = 800;
|
||||
else
|
||||
ast->mclk = 396;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mcr_cfg & 0x40)
|
||||
ast->dram_bus_width = 16;
|
||||
else
|
||||
ast->dram_bus_width = 32;
|
||||
|
||||
if (IS_AST_GEN6(ast)) {
|
||||
switch (mcr_cfg & 0x03) {
|
||||
case 0:
|
||||
ast->dram_type = AST_DRAM_1Gx16;
|
||||
break;
|
||||
default:
|
||||
case 1:
|
||||
ast->dram_type = AST_DRAM_2Gx16;
|
||||
break;
|
||||
case 2:
|
||||
ast->dram_type = AST_DRAM_4Gx16;
|
||||
break;
|
||||
case 3:
|
||||
ast->dram_type = AST_DRAM_8Gx16;
|
||||
break;
|
||||
}
|
||||
} else if (IS_AST_GEN4(ast) || IS_AST_GEN5(ast)) {
|
||||
switch (mcr_cfg & 0x03) {
|
||||
case 0:
|
||||
ast->dram_type = AST_DRAM_512Mx16;
|
||||
break;
|
||||
default:
|
||||
case 1:
|
||||
ast->dram_type = AST_DRAM_1Gx16;
|
||||
break;
|
||||
case 2:
|
||||
ast->dram_type = AST_DRAM_2Gx16;
|
||||
break;
|
||||
case 3:
|
||||
ast->dram_type = AST_DRAM_4Gx16;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (mcr_cfg & 0x0c) {
|
||||
case 0:
|
||||
case 4:
|
||||
ast->dram_type = AST_DRAM_512Mx16;
|
||||
break;
|
||||
case 8:
|
||||
if (mcr_cfg & 0x40)
|
||||
ast->dram_type = AST_DRAM_1Gx16;
|
||||
else
|
||||
ast->dram_type = AST_DRAM_512Mx32;
|
||||
break;
|
||||
case 0xc:
|
||||
ast->dram_type = AST_DRAM_1Gx32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mcr_scu_strap & 0x2000)
|
||||
ref_pll = 14318;
|
||||
else
|
||||
ref_pll = 12000;
|
||||
|
||||
denum = mcr_scu_mpll & 0x1f;
|
||||
num = (mcr_scu_mpll & 0x3fe0) >> 5;
|
||||
dsel = (mcr_scu_mpll & 0xc000) >> 14;
|
||||
switch (dsel) {
|
||||
case 3:
|
||||
div = 0x4;
|
||||
break;
|
||||
case 2:
|
||||
case 1:
|
||||
div = 0x2;
|
||||
break;
|
||||
default:
|
||||
div = 0x1;
|
||||
break;
|
||||
}
|
||||
ast->mclk = ref_pll * (num + 2) / ((denum + 2) * (div * 1000));
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct drm_device *ast_device_create(struct pci_dev *pdev,
|
||||
const struct drm_driver *drv,
|
||||
enum ast_chip chip,
|
||||
@@ -352,12 +232,6 @@ struct drm_device *ast_device_create(struct pci_dev *pdev,
|
||||
ast->regs = regs;
|
||||
ast->ioregs = ioregs;
|
||||
|
||||
ret = ast_get_dram_info(ast);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
drm_info(dev, "dram MCLK=%u Mhz type=%d bus_width=%d\n",
|
||||
ast->mclk, ast->dram_type, ast->dram_bus_width);
|
||||
|
||||
ast_detect_tx_chip(ast, need_post);
|
||||
switch (ast->tx_chip) {
|
||||
case AST_TX_ASTDP:
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include <sound/soc.h>
|
||||
#include <linux/of_graph.h>
|
||||
|
||||
#include <drm/display/drm_hdmi_state_helper.h>
|
||||
|
||||
#include "adv7511.h"
|
||||
|
||||
static void adv7511_calc_cts_n(unsigned int f_tmds, unsigned int fs,
|
||||
@@ -155,17 +157,8 @@ int adv7511_hdmi_audio_prepare(struct drm_bridge *bridge,
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_I2C_FREQ_ID_CFG,
|
||||
ADV7511_I2C_FREQ_ID_CFG_RATE_MASK, rate << 4);
|
||||
|
||||
/* send current Audio infoframe values while updating */
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
|
||||
BIT(5), BIT(5));
|
||||
|
||||
regmap_write(adv7511->regmap, ADV7511_REG_AUDIO_INFOFRAME(0), 0x1);
|
||||
|
||||
/* use Audio infoframe updated info */
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
|
||||
BIT(5), 0);
|
||||
|
||||
return 0;
|
||||
return drm_atomic_helper_connector_hdmi_update_audio_infoframe(connector,
|
||||
&hparms->cea);
|
||||
}
|
||||
|
||||
int adv7511_hdmi_audio_startup(struct drm_bridge *bridge,
|
||||
@@ -188,15 +181,9 @@ int adv7511_hdmi_audio_startup(struct drm_bridge *bridge,
|
||||
/* not copyrighted */
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CFG1,
|
||||
BIT(5), BIT(5));
|
||||
/* enable audio infoframes */
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1,
|
||||
BIT(3), BIT(3));
|
||||
/* AV mute disable */
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_GC(0),
|
||||
BIT(7) | BIT(6), BIT(7));
|
||||
/* use Audio infoframe updated info */
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
|
||||
BIT(5), 0);
|
||||
|
||||
/* enable SPDIF receiver */
|
||||
if (adv7511->audio_source == ADV7511_AUDIO_SOURCE_SPDIF)
|
||||
@@ -214,4 +201,6 @@ void adv7511_hdmi_audio_shutdown(struct drm_bridge *bridge,
|
||||
if (adv7511->audio_source == ADV7511_AUDIO_SOURCE_SPDIF)
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG,
|
||||
BIT(7), 0);
|
||||
|
||||
drm_atomic_helper_connector_hdmi_clear_audio_infoframe(connector);
|
||||
}
|
||||
|
||||
@@ -893,6 +893,9 @@ static int adv7511_bridge_hdmi_clear_infoframe(struct drm_bridge *bridge,
|
||||
struct adv7511 *adv7511 = bridge_to_adv7511(bridge);
|
||||
|
||||
switch (type) {
|
||||
case HDMI_INFOFRAME_TYPE_AUDIO:
|
||||
adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_AUDIO_INFOFRAME);
|
||||
break;
|
||||
case HDMI_INFOFRAME_TYPE_AVI:
|
||||
adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_AVI_INFOFRAME);
|
||||
break;
|
||||
@@ -916,22 +919,48 @@ static int adv7511_bridge_hdmi_write_infoframe(struct drm_bridge *bridge,
|
||||
{
|
||||
struct adv7511 *adv7511 = bridge_to_adv7511(bridge);
|
||||
|
||||
adv7511_bridge_hdmi_clear_infoframe(bridge, type);
|
||||
|
||||
switch (type) {
|
||||
case HDMI_INFOFRAME_TYPE_AUDIO:
|
||||
/* send current Audio infoframe values while updating */
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
|
||||
BIT(5), BIT(5));
|
||||
|
||||
/* The Audio infoframe id is not configurable */
|
||||
regmap_bulk_write(adv7511->regmap, ADV7511_REG_AUDIO_INFOFRAME_VERSION,
|
||||
buffer + 1, len - 1);
|
||||
|
||||
/* use Audio infoframe updated info */
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
|
||||
BIT(5), 0);
|
||||
|
||||
adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_AUDIO_INFOFRAME);
|
||||
break;
|
||||
case HDMI_INFOFRAME_TYPE_AVI:
|
||||
/* send current AVI infoframe values while updating */
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
|
||||
BIT(6), BIT(6));
|
||||
|
||||
/* The AVI infoframe id is not configurable */
|
||||
regmap_bulk_write(adv7511->regmap, ADV7511_REG_AVI_INFOFRAME_VERSION,
|
||||
buffer + 1, len - 1);
|
||||
|
||||
regmap_write(adv7511->regmap, ADV7511_REG_AUDIO_INFOFRAME_LENGTH, 0x2);
|
||||
regmap_write(adv7511->regmap, ADV7511_REG_AUDIO_INFOFRAME(1), 0x1);
|
||||
|
||||
/* use AVI infoframe updated info */
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
|
||||
BIT(6), 0);
|
||||
|
||||
adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_AVI_INFOFRAME);
|
||||
break;
|
||||
case HDMI_INFOFRAME_TYPE_SPD:
|
||||
adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_SPD);
|
||||
regmap_bulk_write(adv7511->regmap_packet, ADV7511_PACKET_SPD(0),
|
||||
buffer, len);
|
||||
adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_SPD);
|
||||
break;
|
||||
case HDMI_INFOFRAME_TYPE_VENDOR:
|
||||
adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_SPARE1);
|
||||
regmap_bulk_write(adv7511->regmap_packet, ADV7511_PACKET_SPARE1(0),
|
||||
buffer, len);
|
||||
adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_SPARE1);
|
||||
|
||||
@@ -6,6 +6,7 @@ config DRM_CDNS_DSI
|
||||
select DRM_PANEL_BRIDGE
|
||||
select GENERIC_PHY
|
||||
select GENERIC_PHY_MIPI_DPHY
|
||||
select VIDEOMODE_HELPERS
|
||||
depends on OF
|
||||
help
|
||||
Support Cadence DPI to DSI bridge. This is an internal
|
||||
|
||||
@@ -146,6 +146,7 @@
|
||||
#define HDMI_COLOR_DEPTH_24 FIELD_PREP(HDMI_COLOR_DEPTH, 4)
|
||||
|
||||
#define HDMI_REG_PKT_GENERAL_CTRL 0xc6
|
||||
#define HDMI_REG_PKT_NULL_CTRL 0xc9
|
||||
#define HDMI_REG_AVI_INFOFRM_CTRL 0xcd
|
||||
#define ENABLE_PKT BIT(0)
|
||||
#define REPEAT_PKT BIT(1)
|
||||
@@ -154,6 +155,12 @@
|
||||
* 3) HDMI register bank1: 0x130 ~ 0x1ff (HDMI packet registers)
|
||||
*/
|
||||
|
||||
/* NULL packet registers */
|
||||
/* Header Byte(HB): n = 0 ~ 2 */
|
||||
#define HDMI_REG_PKT_HB(n) (0x138 + (n))
|
||||
/* Packet Byte(PB): n = 0 ~ 27(HDMI_MAX_INFOFRAME_SIZE), n = 0 for checksum */
|
||||
#define HDMI_REG_PKT_PB(n) (0x13b + (n))
|
||||
|
||||
/* AVI packet registers */
|
||||
#define HDMI_REG_AVI_DB1 0x158
|
||||
#define HDMI_REG_AVI_DB2 0x159
|
||||
@@ -224,7 +231,9 @@ static bool it6263_hdmi_writeable_reg(struct device *dev, unsigned int reg)
|
||||
case HDMI_REG_HDMI_MODE:
|
||||
case HDMI_REG_GCP:
|
||||
case HDMI_REG_PKT_GENERAL_CTRL:
|
||||
case HDMI_REG_PKT_NULL_CTRL:
|
||||
case HDMI_REG_AVI_INFOFRM_CTRL:
|
||||
case HDMI_REG_PKT_HB(0) ... HDMI_REG_PKT_PB(HDMI_MAX_INFOFRAME_SIZE):
|
||||
case HDMI_REG_AVI_DB1:
|
||||
case HDMI_REG_AVI_DB2:
|
||||
case HDMI_REG_AVI_DB3:
|
||||
@@ -755,10 +764,16 @@ static int it6263_hdmi_clear_infoframe(struct drm_bridge *bridge,
|
||||
{
|
||||
struct it6263 *it = bridge_to_it6263(bridge);
|
||||
|
||||
if (type == HDMI_INFOFRAME_TYPE_AVI)
|
||||
switch (type) {
|
||||
case HDMI_INFOFRAME_TYPE_AVI:
|
||||
regmap_write(it->hdmi_regmap, HDMI_REG_AVI_INFOFRM_CTRL, 0);
|
||||
else
|
||||
break;
|
||||
case HDMI_INFOFRAME_TYPE_VENDOR:
|
||||
regmap_write(it->hdmi_regmap, HDMI_REG_PKT_NULL_CTRL, 0);
|
||||
break;
|
||||
default:
|
||||
dev_dbg(it->dev, "unsupported HDMI infoframe 0x%x\n", type);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -770,27 +785,36 @@ static int it6263_hdmi_write_infoframe(struct drm_bridge *bridge,
|
||||
struct it6263 *it = bridge_to_it6263(bridge);
|
||||
struct regmap *regmap = it->hdmi_regmap;
|
||||
|
||||
if (type != HDMI_INFOFRAME_TYPE_AVI) {
|
||||
switch (type) {
|
||||
case HDMI_INFOFRAME_TYPE_AVI:
|
||||
/* write the first AVI infoframe data byte chunk(DB1-DB5) */
|
||||
regmap_bulk_write(regmap, HDMI_REG_AVI_DB1,
|
||||
&buffer[HDMI_INFOFRAME_HEADER_SIZE],
|
||||
HDMI_AVI_DB_CHUNK1_SIZE);
|
||||
|
||||
/* write the second AVI infoframe data byte chunk(DB6-DB13) */
|
||||
regmap_bulk_write(regmap, HDMI_REG_AVI_DB6,
|
||||
&buffer[HDMI_INFOFRAME_HEADER_SIZE +
|
||||
HDMI_AVI_DB_CHUNK1_SIZE],
|
||||
HDMI_AVI_DB_CHUNK2_SIZE);
|
||||
|
||||
/* write checksum */
|
||||
regmap_write(regmap, HDMI_REG_AVI_CSUM, buffer[3]);
|
||||
|
||||
regmap_write(regmap, HDMI_REG_AVI_INFOFRM_CTRL,
|
||||
ENABLE_PKT | REPEAT_PKT);
|
||||
break;
|
||||
case HDMI_INFOFRAME_TYPE_VENDOR:
|
||||
/* write header and payload */
|
||||
regmap_bulk_write(regmap, HDMI_REG_PKT_HB(0), buffer, len);
|
||||
|
||||
regmap_write(regmap, HDMI_REG_PKT_NULL_CTRL,
|
||||
ENABLE_PKT | REPEAT_PKT);
|
||||
break;
|
||||
default:
|
||||
dev_dbg(it->dev, "unsupported HDMI infoframe 0x%x\n", type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* write the first AVI infoframe data byte chunk(DB1-DB5) */
|
||||
regmap_bulk_write(regmap, HDMI_REG_AVI_DB1,
|
||||
&buffer[HDMI_INFOFRAME_HEADER_SIZE],
|
||||
HDMI_AVI_DB_CHUNK1_SIZE);
|
||||
|
||||
/* write the second AVI infoframe data byte chunk(DB6-DB13) */
|
||||
regmap_bulk_write(regmap, HDMI_REG_AVI_DB6,
|
||||
&buffer[HDMI_INFOFRAME_HEADER_SIZE +
|
||||
HDMI_AVI_DB_CHUNK1_SIZE],
|
||||
HDMI_AVI_DB_CHUNK2_SIZE);
|
||||
|
||||
/* write checksum */
|
||||
regmap_write(regmap, HDMI_REG_AVI_CSUM, buffer[3]);
|
||||
|
||||
regmap_write(regmap, HDMI_REG_AVI_INFOFRM_CTRL, ENABLE_PKT | REPEAT_PKT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -266,6 +266,11 @@ static const struct of_device_id simple_bridge_match[] = {
|
||||
.data = &(const struct simple_bridge_info) {
|
||||
.connector_type = DRM_MODE_CONNECTOR_HDMIA,
|
||||
},
|
||||
}, {
|
||||
.compatible = "realtek,rtd2171",
|
||||
.data = &(const struct simple_bridge_info) {
|
||||
.connector_type = DRM_MODE_CONNECTOR_HDMIA,
|
||||
},
|
||||
}, {
|
||||
.compatible = "ti,opa362",
|
||||
.data = &(const struct simple_bridge_info) {
|
||||
|
||||
@@ -776,8 +776,6 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
|
||||
if (!connector->ycbcr_420_allowed)
|
||||
supported_formats &= ~BIT(HDMI_COLORSPACE_YUV420);
|
||||
|
||||
bridge = bridge_connector->bridge_hdmi;
|
||||
|
||||
ret = drmm_connector_hdmi_init(drm, connector,
|
||||
bridge_connector->bridge_hdmi->vendor,
|
||||
bridge_connector->bridge_hdmi->product,
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
@@ -30,6 +31,8 @@
|
||||
#include <drm/drm_property.h>
|
||||
#include <drm/drm_sysfs.h>
|
||||
|
||||
#include <asm/video.h>
|
||||
|
||||
#include "drm_internal.h"
|
||||
#include "drm_crtc_internal.h"
|
||||
|
||||
@@ -508,6 +511,43 @@ void drm_sysfs_connector_property_event(struct drm_connector *connector,
|
||||
}
|
||||
EXPORT_SYMBOL(drm_sysfs_connector_property_event);
|
||||
|
||||
static ssize_t boot_display_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return sysfs_emit(buf, "1\n");
|
||||
}
|
||||
static DEVICE_ATTR_RO(boot_display);
|
||||
|
||||
static struct attribute *display_attrs[] = {
|
||||
&dev_attr_boot_display.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static umode_t boot_display_visible(struct kobject *kobj,
|
||||
struct attribute *a, int n)
|
||||
{
|
||||
struct device *dev = kobj_to_dev(kobj)->parent;
|
||||
|
||||
if (dev_is_pci(dev)) {
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
|
||||
if (video_is_primary_device(&pdev->dev))
|
||||
return a->mode;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct attribute_group display_attr_group = {
|
||||
.attrs = display_attrs,
|
||||
.is_visible = boot_display_visible,
|
||||
};
|
||||
|
||||
static const struct attribute_group *card_dev_groups[] = {
|
||||
&display_attr_group,
|
||||
NULL
|
||||
};
|
||||
|
||||
struct device *drm_sysfs_minor_alloc(struct drm_minor *minor)
|
||||
{
|
||||
const char *minor_str;
|
||||
@@ -531,6 +571,7 @@ struct device *drm_sysfs_minor_alloc(struct drm_minor *minor)
|
||||
|
||||
kdev->devt = MKDEV(DRM_MAJOR, minor->index);
|
||||
kdev->class = drm_class;
|
||||
kdev->groups = card_dev_groups;
|
||||
kdev->type = &drm_sysfs_device_minor;
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +120,6 @@ static void psb_fbdev_fb_destroy(struct fb_info *info)
|
||||
drm_fb_helper_fini(fb_helper);
|
||||
|
||||
drm_framebuffer_unregister_private(fb);
|
||||
fb->obj[0] = NULL;
|
||||
drm_framebuffer_cleanup(fb);
|
||||
kfree(fb);
|
||||
|
||||
@@ -245,7 +244,6 @@ int psb_fbdev_driver_fbdev_probe(struct drm_fb_helper *fb_helper,
|
||||
|
||||
err_drm_framebuffer_unregister_private:
|
||||
drm_framebuffer_unregister_private(fb);
|
||||
fb->obj[0] = NULL;
|
||||
drm_framebuffer_cleanup(fb);
|
||||
kfree(fb);
|
||||
err_drm_gem_object_put:
|
||||
|
||||
@@ -108,9 +108,21 @@ struct dma_buf *nouveau_gem_prime_export(struct drm_gem_object *gobj,
|
||||
int flags)
|
||||
{
|
||||
struct nouveau_bo *nvbo = nouveau_gem_object(gobj);
|
||||
struct ttm_operation_ctx ctx = {
|
||||
.interruptible = true,
|
||||
.no_wait_gpu = true,
|
||||
/* We opt to avoid OOM on system pages allocations */
|
||||
.gfp_retry_mayfail = true,
|
||||
.allow_res_evict = false,
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (nvbo->no_share)
|
||||
return ERR_PTR(-EPERM);
|
||||
|
||||
ret = ttm_bo_setup_export(&nvbo->bo, &ctx);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
return drm_gem_prime_export(gobj, flags);
|
||||
}
|
||||
|
||||
@@ -1843,6 +1843,13 @@ static const struct panel_delay delay_200_500_e50_d100 = {
|
||||
.disable = 100,
|
||||
};
|
||||
|
||||
static const struct panel_delay delay_80_500_e50_d50 = {
|
||||
.hpd_absent = 80,
|
||||
.unprepare = 500,
|
||||
.enable = 50,
|
||||
.disable = 50,
|
||||
};
|
||||
|
||||
#define EDP_PANEL_ENTRY(vend_chr_0, vend_chr_1, vend_chr_2, product_id, _delay, _name) \
|
||||
{ \
|
||||
.ident = { \
|
||||
@@ -1955,6 +1962,7 @@ static const struct edp_panel_entry edp_panels[] = {
|
||||
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0a36, &delay_200_500_e200, "Unknown"),
|
||||
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0a3e, &delay_200_500_e80_d50, "NV116WHM-N49"),
|
||||
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0a5d, &delay_200_500_e50, "NV116WHM-N45"),
|
||||
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0a6a, &delay_200_500_e80, "NV140WUM-N44"),
|
||||
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0ac5, &delay_200_500_e50, "NV116WHM-N4C"),
|
||||
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0ae8, &delay_200_500_e50_p2e80, "NV140WUM-N41"),
|
||||
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0b09, &delay_200_500_e50_po2e200, "NV140FHM-NZ"),
|
||||
@@ -1996,6 +2004,7 @@ static const struct edp_panel_entry edp_panels[] = {
|
||||
EDP_PANEL_ENTRY('C', 'M', 'N', 0x124c, &delay_200_500_e80_d50, "N122JCA-ENK"),
|
||||
EDP_PANEL_ENTRY('C', 'M', 'N', 0x142b, &delay_200_500_e80_d50, "N140HCA-EAC"),
|
||||
EDP_PANEL_ENTRY('C', 'M', 'N', 0x142e, &delay_200_500_e80_d50, "N140BGA-EA4"),
|
||||
EDP_PANEL_ENTRY('C', 'M', 'N', 0x1441, &delay_200_500_e80_d50, "N140JCA-ELK"),
|
||||
EDP_PANEL_ENTRY('C', 'M', 'N', 0x144f, &delay_200_500_e80_d50, "N140HGA-EA1"),
|
||||
EDP_PANEL_ENTRY('C', 'M', 'N', 0x1468, &delay_200_500_e80, "N140HGA-EA1"),
|
||||
EDP_PANEL_ENTRY('C', 'M', 'N', 0x14a8, &delay_200_500_e80, "N140JCA-ELP"),
|
||||
@@ -2011,10 +2020,12 @@ static const struct edp_panel_entry edp_panels[] = {
|
||||
EDP_PANEL_ENTRY('C', 'S', 'W', 0x1100, &delay_200_500_e80_d50, "MNB601LS1-1"),
|
||||
EDP_PANEL_ENTRY('C', 'S', 'W', 0x1103, &delay_200_500_e80_d50, "MNB601LS1-3"),
|
||||
EDP_PANEL_ENTRY('C', 'S', 'W', 0x1104, &delay_200_500_e50_d100, "MNB601LS1-4"),
|
||||
EDP_PANEL_ENTRY('C', 'S', 'W', 0x143f, &delay_200_500_e50, "MNE007QS3-6"),
|
||||
EDP_PANEL_ENTRY('C', 'S', 'W', 0x1448, &delay_200_500_e50, "MNE007QS3-7"),
|
||||
EDP_PANEL_ENTRY('C', 'S', 'W', 0x1457, &delay_80_500_e80_p2e200, "MNE007QS3-8"),
|
||||
EDP_PANEL_ENTRY('C', 'S', 'W', 0x1462, &delay_200_500_e50, "MNE007QS5-2"),
|
||||
EDP_PANEL_ENTRY('C', 'S', 'W', 0x1468, &delay_200_500_e50, "MNE007QB2-2"),
|
||||
EDP_PANEL_ENTRY('C', 'S', 'W', 0x146e, &delay_80_500_e50_d50, "MNE007QB3-1"),
|
||||
|
||||
EDP_PANEL_ENTRY('E', 'T', 'C', 0x0000, &delay_50_500_e200_d200_po2e335, "LP079QX1-SP0V"),
|
||||
|
||||
|
||||
@@ -28,8 +28,6 @@ struct panel_lvds {
|
||||
struct device *dev;
|
||||
|
||||
const char *label;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
struct drm_display_mode dmode;
|
||||
u32 bus_flags;
|
||||
unsigned int bus_format;
|
||||
|
||||
@@ -1013,7 +1013,7 @@ static int rcar_lvds_runtime_resume(struct device *dev)
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops rcar_lvds_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(rcar_lvds_runtime_suspend, rcar_lvds_runtime_resume, NULL)
|
||||
RUNTIME_PM_OPS(rcar_lvds_runtime_suspend, rcar_lvds_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static struct platform_driver rcar_lvds_platform_driver = {
|
||||
@@ -1021,7 +1021,7 @@ static struct platform_driver rcar_lvds_platform_driver = {
|
||||
.remove = rcar_lvds_remove,
|
||||
.driver = {
|
||||
.name = "rcar-lvds",
|
||||
.pm = &rcar_lvds_pm_ops,
|
||||
.pm = pm_ptr(&rcar_lvds_pm_ops),
|
||||
.of_match_table = rcar_lvds_of_table,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -937,9 +937,234 @@ static int rcar_mipi_dsi_host_detach(struct mipi_dsi_host *host,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t rcar_mipi_dsi_host_tx_transfer(struct mipi_dsi_host *host,
|
||||
const struct mipi_dsi_msg *msg,
|
||||
bool is_rx_xfer)
|
||||
{
|
||||
const bool is_tx_long = mipi_dsi_packet_format_is_long(msg->type);
|
||||
struct rcar_mipi_dsi *dsi = host_to_rcar_mipi_dsi(host);
|
||||
struct mipi_dsi_packet packet;
|
||||
u8 payload[16] = { 0 };
|
||||
u32 status;
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_create_packet(&packet, msg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Configure LP or HS command transfer. */
|
||||
rcar_mipi_dsi_write(dsi, TXCMSETR, (msg->flags & MIPI_DSI_MSG_USE_LPM) ?
|
||||
TXCMSETR_SPDTYP : 0);
|
||||
|
||||
/* Register access mode for RX transfer. */
|
||||
if (is_rx_xfer)
|
||||
rcar_mipi_dsi_write(dsi, RXPSETR, 0);
|
||||
|
||||
/* Do not use IRQ, poll for completion, the completion is quick. */
|
||||
rcar_mipi_dsi_write(dsi, TXCMIER, 0);
|
||||
|
||||
/*
|
||||
* Send the header:
|
||||
* header[0] = Virtual Channel + Data Type
|
||||
* header[1] = Word Count LSB (LP) or first param (SP)
|
||||
* header[2] = Word Count MSB (LP) or second param (SP)
|
||||
*/
|
||||
rcar_mipi_dsi_write(dsi, TXCMPHDR,
|
||||
(is_tx_long ? TXCMPHDR_FMT : 0) |
|
||||
TXCMPHDR_VC(msg->channel) |
|
||||
TXCMPHDR_DT(msg->type) |
|
||||
TXCMPHDR_DATA1(packet.header[2]) |
|
||||
TXCMPHDR_DATA0(packet.header[1]));
|
||||
|
||||
if (is_tx_long) {
|
||||
memcpy(payload, packet.payload,
|
||||
min(msg->tx_len, sizeof(payload)));
|
||||
|
||||
rcar_mipi_dsi_write(dsi, TXCMPPD0R,
|
||||
(payload[3] << 24) | (payload[2] << 16) |
|
||||
(payload[1] << 8) | payload[0]);
|
||||
rcar_mipi_dsi_write(dsi, TXCMPPD1R,
|
||||
(payload[7] << 24) | (payload[6] << 16) |
|
||||
(payload[5] << 8) | payload[4]);
|
||||
rcar_mipi_dsi_write(dsi, TXCMPPD2R,
|
||||
(payload[11] << 24) | (payload[10] << 16) |
|
||||
(payload[9] << 8) | payload[8]);
|
||||
rcar_mipi_dsi_write(dsi, TXCMPPD3R,
|
||||
(payload[15] << 24) | (payload[14] << 16) |
|
||||
(payload[13] << 8) | payload[12]);
|
||||
}
|
||||
|
||||
/* Start the transfer, RX with BTA, TX without BTA. */
|
||||
if (is_rx_xfer) {
|
||||
rcar_mipi_dsi_write(dsi, TXCMCR, TXCMCR_BTAREQ);
|
||||
|
||||
/* Wait until the transmission, BTA, reception completed. */
|
||||
ret = read_poll_timeout(rcar_mipi_dsi_read, status,
|
||||
(status & RXPSR_BTAREQEND),
|
||||
2000, 50000, false, dsi, RXPSR);
|
||||
} else {
|
||||
rcar_mipi_dsi_write(dsi, TXCMCR, TXCMCR_TXREQ);
|
||||
|
||||
/* Wait until the transmission completed. */
|
||||
ret = read_poll_timeout(rcar_mipi_dsi_read, status,
|
||||
(status & TXCMSR_TXREQEND),
|
||||
2000, 50000, false, dsi, TXCMSR);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(dsi->dev, "Command transfer timeout (0x%08x)\n",
|
||||
status);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return packet.size;
|
||||
}
|
||||
|
||||
static ssize_t rcar_mipi_dsi_host_rx_transfer(struct mipi_dsi_host *host,
|
||||
const struct mipi_dsi_msg *msg)
|
||||
{
|
||||
struct rcar_mipi_dsi *dsi = host_to_rcar_mipi_dsi(host);
|
||||
u8 *rx_buf = (u8 *)(msg->rx_buf);
|
||||
u32 reg, data, status, wc;
|
||||
int i, ret;
|
||||
|
||||
/* RX transfer received data validation and parsing starts here. */
|
||||
reg = rcar_mipi_dsi_read(dsi, TOSR);
|
||||
if (reg & TOSR_TATO) { /* Turn-Around TimeOut. */
|
||||
/* Clear TATO Turn-Around TimeOut bit. */
|
||||
rcar_mipi_dsi_write(dsi, TOSR, TOSR_TATO);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
reg = rcar_mipi_dsi_read(dsi, RXPSR);
|
||||
|
||||
if (msg->flags & MIPI_DSI_MSG_REQ_ACK) {
|
||||
/* Transfer with zero-length RX. */
|
||||
if (!(reg & RXPSR_RCVACK)) {
|
||||
/* No ACK on RX response received. */
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
/* Transfer with non-zero-length RX. */
|
||||
if (!(reg & RXPSR_RCVRESP)) {
|
||||
/* No packet header of RX response received. */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (reg & (RXPSR_CRCERR | RXPSR_WCERR | RXPSR_AXIERR | RXPSR_OVRERR)) {
|
||||
/* Incorrect response payload. */
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
data = rcar_mipi_dsi_read(dsi, RXPHDR);
|
||||
if (data & RXPHDR_FMT) { /* Long Packet Response. */
|
||||
/* Read Long Packet Response length from packet header. */
|
||||
wc = data & 0xffff;
|
||||
if (wc > msg->rx_len) {
|
||||
dev_warn(dsi->dev,
|
||||
"Long Packet Response longer than RX buffer (%d), limited to %zu Bytes\n",
|
||||
wc, msg->rx_len);
|
||||
wc = msg->rx_len;
|
||||
}
|
||||
|
||||
if (wc > 16) {
|
||||
dev_warn(dsi->dev,
|
||||
"Long Packet Response too long (%d), limited to 16 Bytes\n",
|
||||
wc);
|
||||
wc = 16;
|
||||
}
|
||||
|
||||
for (i = 0; i < msg->rx_len; i++) {
|
||||
if (!(i % 4))
|
||||
data = rcar_mipi_dsi_read(dsi, RXPPD0R + i);
|
||||
|
||||
rx_buf[i] = data & 0xff;
|
||||
data >>= 8;
|
||||
}
|
||||
} else { /* Short Packet Response. */
|
||||
if (msg->rx_len >= 1)
|
||||
rx_buf[0] = data & 0xff;
|
||||
if (msg->rx_len >= 2)
|
||||
rx_buf[1] = (data >> 8) & 0xff;
|
||||
if (msg->rx_len >= 3) {
|
||||
dev_warn(dsi->dev,
|
||||
"Expected Short Packet Response too long (%zu), limited to 2 Bytes\n",
|
||||
msg->rx_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (reg & RXPSR_RCVAKE) {
|
||||
/* Acknowledge and Error report received. */
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Wait until the bus handover to host processor completed. */
|
||||
ret = read_poll_timeout(rcar_mipi_dsi_read, status,
|
||||
!(status & PPIDL0SR_DIR),
|
||||
2000, 50000, false, dsi, PPIDL0SR);
|
||||
if (ret < 0) {
|
||||
dev_err(dsi->dev, "Command RX DIR timeout (0x%08x)\n", status);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Wait until the data lane is in LP11 stop state. */
|
||||
ret = read_poll_timeout(rcar_mipi_dsi_read, status,
|
||||
status & PPIDL0SR_STPST,
|
||||
2000, 50000, false, dsi, PPIDL0SR);
|
||||
if (ret < 0) {
|
||||
dev_err(dsi->dev, "Command RX STPST timeout (0x%08x)\n", status);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t rcar_mipi_dsi_host_transfer(struct mipi_dsi_host *host,
|
||||
const struct mipi_dsi_msg *msg)
|
||||
{
|
||||
const bool is_rx_xfer = (msg->flags & MIPI_DSI_MSG_REQ_ACK) || msg->rx_len;
|
||||
struct rcar_mipi_dsi *dsi = host_to_rcar_mipi_dsi(host);
|
||||
int ret;
|
||||
|
||||
if (msg->tx_len > 16 || msg->rx_len > 16) {
|
||||
/* ToDo: Implement Memory on AXI bus command mode. */
|
||||
dev_warn(dsi->dev,
|
||||
"Register-based command mode supports only up to 16 Bytes long payload\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
ret = rcar_mipi_dsi_host_tx_transfer(host, msg, is_rx_xfer);
|
||||
|
||||
/* If TX transfer succeeded and this transfer has RX part. */
|
||||
if (ret >= 0 && is_rx_xfer) {
|
||||
ret = rcar_mipi_dsi_host_rx_transfer(host, msg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = msg->rx_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait a bit between commands, otherwise panels based on ILI9881C
|
||||
* TCON may fail to correctly receive all commands sent to them.
|
||||
* Until we can actually test with another DSI device, keep the
|
||||
* delay here, but eventually this delay might have to be moved
|
||||
* into the ILI9881C panel driver.
|
||||
*/
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
/* Clear the completion interrupt. */
|
||||
if (!msg->rx_len)
|
||||
rcar_mipi_dsi_write(dsi, TXCMSR, TXCMSR_TXREQEND);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct mipi_dsi_host_ops rcar_mipi_dsi_host_ops = {
|
||||
.attach = rcar_mipi_dsi_host_attach,
|
||||
.detach = rcar_mipi_dsi_host_detach,
|
||||
.transfer = rcar_mipi_dsi_host_transfer
|
||||
};
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
@@ -15,6 +15,127 @@
|
||||
#define TXSETR 0x100
|
||||
#define TXSETR_LANECNT_MASK (0x3 << 0)
|
||||
|
||||
/*
|
||||
* DSI Command Transfer Registers
|
||||
*/
|
||||
#define TXCMSETR 0x110
|
||||
#define TXCMSETR_SPDTYP (1 << 8) /* 0:HS 1:LP */
|
||||
#define TXCMSETR_LPPDACC (1 << 0)
|
||||
#define TXCMCR 0x120
|
||||
#define TXCMCR_BTATYP (1 << 2)
|
||||
#define TXCMCR_BTAREQ (1 << 1)
|
||||
#define TXCMCR_TXREQ (1 << 0)
|
||||
#define TXCMSR 0x130
|
||||
#define TXCMSR_CLSNERR (1 << 18)
|
||||
#define TXCMSR_AXIERR (1 << 16)
|
||||
#define TXCMSR_TXREQEND (1 << 0)
|
||||
#define TXCMSCR 0x134
|
||||
#define TXCMSCR_CLSNERR (1 << 18)
|
||||
#define TXCMSCR_AXIERR (1 << 16)
|
||||
#define TXCMSCR_TXREQEND (1 << 0)
|
||||
#define TXCMIER 0x138
|
||||
#define TXCMIER_CLSNERR (1 << 18)
|
||||
#define TXCMIER_AXIERR (1 << 16)
|
||||
#define TXCMIER_TXREQEND (1 << 0)
|
||||
#define TXCMADDRSET0R 0x140
|
||||
#define TXCMPHDR 0x150
|
||||
#define TXCMPHDR_FMT (1 << 24) /* 0:SP 1:LP */
|
||||
#define TXCMPHDR_VC(n) (((n) & 0x3) << 22)
|
||||
#define TXCMPHDR_DT(n) (((n) & 0x3f) << 16)
|
||||
#define TXCMPHDR_DATA1(n) (((n) & 0xff) << 8)
|
||||
#define TXCMPHDR_DATA0(n) (((n) & 0xff) << 0)
|
||||
#define TXCMPPD0R 0x160
|
||||
#define TXCMPPD1R 0x164
|
||||
#define TXCMPPD2R 0x168
|
||||
#define TXCMPPD3R 0x16c
|
||||
|
||||
#define RXSETR 0x200
|
||||
#define RXSETR_CRCEN (((n) & 0xf) << 24)
|
||||
#define RXSETR_ECCEN (((n) & 0xf) << 16)
|
||||
#define RXPSETR 0x210
|
||||
#define RXPSETR_LPPDACC (1 << 0)
|
||||
#define RXPSR 0x220
|
||||
#define RXPSR_ECCERR1B (1 << 28)
|
||||
#define RXPSR_UEXTRGERR (1 << 25)
|
||||
#define RXPSR_RESPTOERR (1 << 24)
|
||||
#define RXPSR_OVRERR (1 << 23)
|
||||
#define RXPSR_AXIERR (1 << 22)
|
||||
#define RXPSR_CRCERR (1 << 21)
|
||||
#define RXPSR_WCERR (1 << 20)
|
||||
#define RXPSR_UEXDTERR (1 << 19)
|
||||
#define RXPSR_UEXPKTERR (1 << 18)
|
||||
#define RXPSR_ECCERR (1 << 17)
|
||||
#define RXPSR_MLFERR (1 << 16)
|
||||
#define RXPSR_RCVACK (1 << 14)
|
||||
#define RXPSR_RCVEOT (1 << 10)
|
||||
#define RXPSR_RCVAKE (1 << 9)
|
||||
#define RXPSR_RCVRESP (1 << 8)
|
||||
#define RXPSR_BTAREQEND (1 << 0)
|
||||
#define RXPSCR 0x224
|
||||
#define RXPSCR_ECCERR1B (1 << 28)
|
||||
#define RXPSCR_UEXTRGERR (1 << 25)
|
||||
#define RXPSCR_RESPTOERR (1 << 24)
|
||||
#define RXPSCR_OVRERR (1 << 23)
|
||||
#define RXPSCR_AXIERR (1 << 22)
|
||||
#define RXPSCR_CRCERR (1 << 21)
|
||||
#define RXPSCR_WCERR (1 << 20)
|
||||
#define RXPSCR_UEXDTERR (1 << 19)
|
||||
#define RXPSCR_UEXPKTERR (1 << 18)
|
||||
#define RXPSCR_ECCERR (1 << 17)
|
||||
#define RXPSCR_MLFERR (1 << 16)
|
||||
#define RXPSCR_RCVACK (1 << 14)
|
||||
#define RXPSCR_RCVEOT (1 << 10)
|
||||
#define RXPSCR_RCVAKE (1 << 9)
|
||||
#define RXPSCR_RCVRESP (1 << 8)
|
||||
#define RXPSCR_BTAREQEND (1 << 0)
|
||||
#define RXPIER 0x228
|
||||
#define RXPIER_ECCERR1B (1 << 28)
|
||||
#define RXPIER_UEXTRGERR (1 << 25)
|
||||
#define RXPIER_RESPTOERR (1 << 24)
|
||||
#define RXPIER_OVRERR (1 << 23)
|
||||
#define RXPIER_AXIERR (1 << 22)
|
||||
#define RXPIER_CRCERR (1 << 21)
|
||||
#define RXPIER_WCERR (1 << 20)
|
||||
#define RXPIER_UEXDTERR (1 << 19)
|
||||
#define RXPIER_UEXPKTERR (1 << 18)
|
||||
#define RXPIER_ECCERR (1 << 17)
|
||||
#define RXPIER_MLFERR (1 << 16)
|
||||
#define RXPIER_RCVACK (1 << 14)
|
||||
#define RXPIER_RCVEOT (1 << 10)
|
||||
#define RXPIER_RCVAKE (1 << 9)
|
||||
#define RXPIER_RCVRESP (1 << 8)
|
||||
#define RXPIER_BTAREQEND (1 << 0)
|
||||
#define RXPADDRSET0R 0x230
|
||||
#define RXPSIZESETR 0x238
|
||||
#define RXPSIZESETR_SIZE(n) (((n) & 0xf) << 3)
|
||||
#define RXPHDR 0x240
|
||||
#define RXPHDR_FMT (1 << 24) /* 0:SP 1:LP */
|
||||
#define RXPHDR_VC(n) (((n) & 0x3) << 22)
|
||||
#define RXPHDR_DT(n) (((n) & 0x3f) << 16)
|
||||
#define RXPHDR_DATA1(n) (((n) & 0xff) << 8)
|
||||
#define RXPHDR_DATA0(n) (((n) & 0xff) << 0)
|
||||
#define RXPPD0R 0x250
|
||||
#define RXPPD1R 0x254
|
||||
#define RXPPD2R 0x258
|
||||
#define RXPPD3R 0x25c
|
||||
#define AKEPR 0x300
|
||||
#define AKEPR_VC(n) (((n) & 0x3) << 22)
|
||||
#define AKEPR_DT(n) (((n) & 0x3f) << 16)
|
||||
#define AKEPR_ERRRPT(n) (((n) & 0xffff) << 0)
|
||||
#define RXRESPTOSETR 0x400
|
||||
#define TACR 0x500
|
||||
#define TASR 0x510
|
||||
#define TASCR 0x514
|
||||
#define TAIER 0x518
|
||||
#define TOSR 0x610
|
||||
#define TOSR_TATO (1 << 2)
|
||||
#define TOSR_LRXHTO (1 << 1)
|
||||
#define TOSR_HRXTO (1 << 0)
|
||||
#define TOSCR 0x614
|
||||
#define TOSCR_TATO (1 << 2)
|
||||
#define TOSCR_LRXHTO (1 << 1)
|
||||
#define TOSCR_HRXTO (1 << 0)
|
||||
|
||||
/*
|
||||
* Video Mode Register
|
||||
*/
|
||||
@@ -100,6 +221,10 @@
|
||||
#define PPICLSCR_HSTOLP (1 << 27)
|
||||
#define PPICLSCR_TOHS (1 << 26)
|
||||
|
||||
#define PPIDL0SR 0x740
|
||||
#define PPIDL0SR_DIR (1 << 10)
|
||||
#define PPIDL0SR_STPST (1 << 6)
|
||||
|
||||
#define PPIDLSR 0x760
|
||||
#define PPIDLSR_STPST (0xf << 0)
|
||||
|
||||
|
||||
@@ -744,7 +744,7 @@ static bool sti_hqvdp_check_hw_scaling(struct sti_hqvdp *hqvdp,
|
||||
|
||||
inv_zy = DIV_ROUND_UP(src_h, dst_h);
|
||||
|
||||
return (inv_zy <= lfw) ? true : false;
|
||||
return inv_zy <= lfw;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -82,6 +82,21 @@ config DRM_PANEL_MIPI_DBI
|
||||
https://github.com/notro/panel-mipi-dbi/wiki.
|
||||
To compile this driver as a module, choose M here.
|
||||
|
||||
config DRM_PIXPAPER
|
||||
tristate "DRM support for PIXPAPER display panels"
|
||||
depends on DRM && SPI
|
||||
select DRM_CLIENT_SELECTION
|
||||
select DRM_GEM_DMA_HELPER
|
||||
select DRM_KMS_HELPER
|
||||
help
|
||||
DRM driver for the Mayqueen Pixpaper e-ink display panel.
|
||||
|
||||
This driver supports small e-paper displays connected over SPI,
|
||||
with a resolution of 122x250 and XRGB8888 framebuffer format.
|
||||
It is intended for low-power embedded applications.
|
||||
|
||||
If M is selected, the module will be built as pixpaper.ko.
|
||||
|
||||
config TINYDRM_HX8357D
|
||||
tristate "DRM support for HX8357D display panels"
|
||||
depends on DRM && SPI
|
||||
|
||||
@@ -6,6 +6,7 @@ obj-$(CONFIG_DRM_BOCHS) += bochs.o
|
||||
obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus-qemu.o
|
||||
obj-$(CONFIG_DRM_GM12U320) += gm12u320.o
|
||||
obj-$(CONFIG_DRM_PANEL_MIPI_DBI) += panel-mipi-dbi.o
|
||||
obj-$(CONFIG_DRM_PIXPAPER) += pixpaper.o
|
||||
obj-$(CONFIG_TINYDRM_HX8357D) += hx8357d.o
|
||||
obj-$(CONFIG_TINYDRM_ILI9163) += ili9163.o
|
||||
obj-$(CONFIG_TINYDRM_ILI9225) += ili9225.o
|
||||
|
||||
@@ -252,7 +252,7 @@ static int bochs_hw_init(struct bochs_device *bochs)
|
||||
}
|
||||
bochs->ioports = 1;
|
||||
} else {
|
||||
dev_err(dev->dev, "I/O ports are not supported\n");
|
||||
drm_err(dev, "I/O ports are not supported\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
||||
1165
drivers/gpu/drm/tiny/pixpaper.c
Normal file
1165
drivers/gpu/drm/tiny/pixpaper.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1283,3 +1283,18 @@ int ttm_bo_populate(struct ttm_buffer_object *bo,
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ttm_bo_populate);
|
||||
|
||||
int ttm_bo_setup_export(struct ttm_buffer_object *bo,
|
||||
struct ttm_operation_ctx *ctx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ttm_bo_reserve(bo, false, false, NULL);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ret = ttm_bo_populate(bo, ctx);
|
||||
ttm_bo_unreserve(bo);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ttm_bo_setup_export);
|
||||
|
||||
@@ -200,6 +200,7 @@ static void vkms_config_test_get_planes(struct kunit *test)
|
||||
KUNIT_ASSERT_EQ(test, n_planes, 0);
|
||||
|
||||
plane_cfg1 = vkms_config_create_plane(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cfg1);
|
||||
vkms_config_for_each_plane(config, plane_cfg) {
|
||||
n_planes++;
|
||||
if (plane_cfg != plane_cfg1)
|
||||
@@ -209,6 +210,7 @@ static void vkms_config_test_get_planes(struct kunit *test)
|
||||
n_planes = 0;
|
||||
|
||||
plane_cfg2 = vkms_config_create_plane(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cfg2);
|
||||
vkms_config_for_each_plane(config, plane_cfg) {
|
||||
n_planes++;
|
||||
if (plane_cfg != plane_cfg1 && plane_cfg != plane_cfg2)
|
||||
@@ -242,6 +244,7 @@ static void vkms_config_test_get_crtcs(struct kunit *test)
|
||||
KUNIT_FAIL(test, "Unexpected CRTC");
|
||||
|
||||
crtc_cfg1 = vkms_config_create_crtc(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_cfg1);
|
||||
KUNIT_ASSERT_EQ(test, vkms_config_get_num_crtcs(config), 1);
|
||||
vkms_config_for_each_crtc(config, crtc_cfg) {
|
||||
if (crtc_cfg != crtc_cfg1)
|
||||
@@ -249,6 +252,7 @@ static void vkms_config_test_get_crtcs(struct kunit *test)
|
||||
}
|
||||
|
||||
crtc_cfg2 = vkms_config_create_crtc(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_cfg2);
|
||||
KUNIT_ASSERT_EQ(test, vkms_config_get_num_crtcs(config), 2);
|
||||
vkms_config_for_each_crtc(config, crtc_cfg) {
|
||||
if (crtc_cfg != crtc_cfg1 && crtc_cfg != crtc_cfg2)
|
||||
@@ -280,6 +284,7 @@ static void vkms_config_test_get_encoders(struct kunit *test)
|
||||
KUNIT_ASSERT_EQ(test, n_encoders, 0);
|
||||
|
||||
encoder_cfg1 = vkms_config_create_encoder(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder_cfg1);
|
||||
vkms_config_for_each_encoder(config, encoder_cfg) {
|
||||
n_encoders++;
|
||||
if (encoder_cfg != encoder_cfg1)
|
||||
@@ -289,6 +294,7 @@ static void vkms_config_test_get_encoders(struct kunit *test)
|
||||
n_encoders = 0;
|
||||
|
||||
encoder_cfg2 = vkms_config_create_encoder(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder_cfg2);
|
||||
vkms_config_for_each_encoder(config, encoder_cfg) {
|
||||
n_encoders++;
|
||||
if (encoder_cfg != encoder_cfg1 && encoder_cfg != encoder_cfg2)
|
||||
@@ -324,6 +330,7 @@ static void vkms_config_test_get_connectors(struct kunit *test)
|
||||
KUNIT_ASSERT_EQ(test, n_connectors, 0);
|
||||
|
||||
connector_cfg1 = vkms_config_create_connector(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, connector_cfg1);
|
||||
vkms_config_for_each_connector(config, connector_cfg) {
|
||||
n_connectors++;
|
||||
if (connector_cfg != connector_cfg1)
|
||||
@@ -333,6 +340,7 @@ static void vkms_config_test_get_connectors(struct kunit *test)
|
||||
n_connectors = 0;
|
||||
|
||||
connector_cfg2 = vkms_config_create_connector(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, connector_cfg2);
|
||||
vkms_config_for_each_connector(config, connector_cfg) {
|
||||
n_connectors++;
|
||||
if (connector_cfg != connector_cfg1 &&
|
||||
@@ -370,7 +378,7 @@ static void vkms_config_test_invalid_plane_number(struct kunit *test)
|
||||
|
||||
/* Invalid: Too many planes */
|
||||
for (n = 0; n <= 32; n++)
|
||||
vkms_config_create_plane(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vkms_config_create_plane(config));
|
||||
|
||||
KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
|
||||
|
||||
@@ -395,6 +403,7 @@ static void vkms_config_test_valid_plane_type(struct kunit *test)
|
||||
|
||||
/* Invalid: No primary plane */
|
||||
plane_cfg = vkms_config_create_plane(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cfg);
|
||||
vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_OVERLAY);
|
||||
err = vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg);
|
||||
KUNIT_EXPECT_EQ(test, err, 0);
|
||||
@@ -402,11 +411,13 @@ static void vkms_config_test_valid_plane_type(struct kunit *test)
|
||||
|
||||
/* Invalid: Multiple primary planes */
|
||||
plane_cfg = vkms_config_create_plane(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cfg);
|
||||
vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY);
|
||||
err = vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg);
|
||||
KUNIT_EXPECT_EQ(test, err, 0);
|
||||
|
||||
plane_cfg = vkms_config_create_plane(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cfg);
|
||||
vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY);
|
||||
err = vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg);
|
||||
KUNIT_EXPECT_EQ(test, err, 0);
|
||||
@@ -419,11 +430,13 @@ static void vkms_config_test_valid_plane_type(struct kunit *test)
|
||||
|
||||
/* Invalid: Multiple cursor planes */
|
||||
plane_cfg = vkms_config_create_plane(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cfg);
|
||||
vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_CURSOR);
|
||||
err = vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg);
|
||||
KUNIT_EXPECT_EQ(test, err, 0);
|
||||
|
||||
plane_cfg = vkms_config_create_plane(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cfg);
|
||||
vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_CURSOR);
|
||||
err = vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg);
|
||||
KUNIT_EXPECT_EQ(test, err, 0);
|
||||
@@ -437,12 +450,16 @@ static void vkms_config_test_valid_plane_type(struct kunit *test)
|
||||
/* Invalid: Second CRTC without primary plane */
|
||||
crtc_cfg = vkms_config_create_crtc(config);
|
||||
encoder_cfg = vkms_config_create_encoder(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_cfg);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder_cfg);
|
||||
|
||||
err = vkms_config_encoder_attach_crtc(encoder_cfg, crtc_cfg);
|
||||
KUNIT_EXPECT_EQ(test, err, 0);
|
||||
KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
|
||||
|
||||
/* Valid: Second CRTC with a primary plane */
|
||||
plane_cfg = vkms_config_create_plane(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cfg);
|
||||
vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY);
|
||||
err = vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg);
|
||||
KUNIT_EXPECT_EQ(test, err, 0);
|
||||
@@ -486,7 +503,7 @@ static void vkms_config_test_invalid_crtc_number(struct kunit *test)
|
||||
|
||||
/* Invalid: Too many CRTCs */
|
||||
for (n = 0; n <= 32; n++)
|
||||
vkms_config_create_crtc(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vkms_config_create_crtc(config));
|
||||
|
||||
KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
|
||||
|
||||
@@ -509,7 +526,7 @@ static void vkms_config_test_invalid_encoder_number(struct kunit *test)
|
||||
|
||||
/* Invalid: Too many encoders */
|
||||
for (n = 0; n <= 32; n++)
|
||||
vkms_config_create_encoder(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vkms_config_create_encoder(config));
|
||||
|
||||
KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
|
||||
|
||||
@@ -531,12 +548,15 @@ static void vkms_config_test_valid_encoder_possible_crtcs(struct kunit *test)
|
||||
|
||||
/* Invalid: Encoder without a possible CRTC */
|
||||
encoder_cfg = vkms_config_create_encoder(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder_cfg);
|
||||
KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
|
||||
|
||||
/* Valid: Second CRTC with shared encoder */
|
||||
crtc_cfg2 = vkms_config_create_crtc(config);
|
||||
|
||||
plane_cfg = vkms_config_create_plane(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_cfg2);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cfg);
|
||||
|
||||
vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY);
|
||||
err = vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg2);
|
||||
KUNIT_EXPECT_EQ(test, err, 0);
|
||||
@@ -577,7 +597,7 @@ static void vkms_config_test_invalid_connector_number(struct kunit *test)
|
||||
|
||||
/* Invalid: Too many connectors */
|
||||
for (n = 0; n <= 32; n++)
|
||||
connector_cfg = vkms_config_create_connector(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vkms_config_create_connector(config));
|
||||
|
||||
KUNIT_EXPECT_FALSE(test, vkms_config_is_valid(config));
|
||||
|
||||
@@ -669,13 +689,19 @@ static void vkms_config_test_plane_attach_crtc(struct kunit *test)
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, config);
|
||||
|
||||
overlay_cfg = vkms_config_create_plane(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, overlay_cfg);
|
||||
vkms_config_plane_set_type(overlay_cfg, DRM_PLANE_TYPE_OVERLAY);
|
||||
|
||||
primary_cfg = vkms_config_create_plane(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, primary_cfg);
|
||||
vkms_config_plane_set_type(primary_cfg, DRM_PLANE_TYPE_PRIMARY);
|
||||
|
||||
cursor_cfg = vkms_config_create_plane(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cursor_cfg);
|
||||
vkms_config_plane_set_type(cursor_cfg, DRM_PLANE_TYPE_CURSOR);
|
||||
|
||||
crtc_cfg = vkms_config_create_crtc(config);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_cfg);
|
||||
|
||||
/* No primary or cursor planes */
|
||||
KUNIT_EXPECT_NULL(test, vkms_config_crtc_primary_plane(config, crtc_cfg));
|
||||
@@ -735,6 +761,11 @@ static void vkms_config_test_plane_get_possible_crtcs(struct kunit *test)
|
||||
crtc_cfg1 = vkms_config_create_crtc(config);
|
||||
crtc_cfg2 = vkms_config_create_crtc(config);
|
||||
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cfg1);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cfg2);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_cfg1);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_cfg2);
|
||||
|
||||
/* No possible CRTCs */
|
||||
vkms_config_plane_for_each_possible_crtc(plane_cfg1, idx, possible_crtc)
|
||||
KUNIT_FAIL(test, "Unexpected possible CRTC");
|
||||
@@ -799,6 +830,11 @@ static void vkms_config_test_encoder_get_possible_crtcs(struct kunit *test)
|
||||
crtc_cfg1 = vkms_config_create_crtc(config);
|
||||
crtc_cfg2 = vkms_config_create_crtc(config);
|
||||
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder_cfg1);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder_cfg2);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_cfg1);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_cfg2);
|
||||
|
||||
/* No possible CRTCs */
|
||||
vkms_config_encoder_for_each_possible_crtc(encoder_cfg1, idx, possible_crtc)
|
||||
KUNIT_FAIL(test, "Unexpected possible CRTC");
|
||||
@@ -863,6 +899,11 @@ static void vkms_config_test_connector_get_possible_encoders(struct kunit *test)
|
||||
encoder_cfg1 = vkms_config_create_encoder(config);
|
||||
encoder_cfg2 = vkms_config_create_encoder(config);
|
||||
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, connector_cfg1);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, connector_cfg2);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder_cfg1);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder_cfg2);
|
||||
|
||||
/* No possible encoders */
|
||||
vkms_config_connector_for_each_possible_encoder(connector_cfg1, idx,
|
||||
possible_encoder)
|
||||
|
||||
@@ -14,20 +14,20 @@
|
||||
MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
|
||||
|
||||
/**
|
||||
* struct pixel_yuv_u8 - Internal representation of a pixel color.
|
||||
* @y: Luma value, stored in 8 bits, without padding, using
|
||||
* struct pixel_yuv_u16 - Internal representation of a pixel color.
|
||||
* @y: Luma value, stored in 16 bits, without padding, using
|
||||
* machine endianness
|
||||
* @u: Blue difference chroma value, stored in 8 bits, without padding, using
|
||||
* @u: Blue difference chroma value, stored in 16 bits, without padding, using
|
||||
* machine endianness
|
||||
* @v: Red difference chroma value, stored in 8 bits, without padding, using
|
||||
* @v: Red difference chroma value, stored in 16 bits, without padding, using
|
||||
* machine endianness
|
||||
*/
|
||||
struct pixel_yuv_u8 {
|
||||
u8 y, u, v;
|
||||
struct pixel_yuv_u16 {
|
||||
u16 y, u, v;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct yuv_u8_to_argb_u16_case - Reference values to test the color
|
||||
* struct yuv_u16_to_argb_u16_case - Reference values to test the color
|
||||
* conversions in VKMS between YUV to ARGB
|
||||
*
|
||||
* @encoding: Encoding used to convert RGB to YUV
|
||||
@@ -39,13 +39,13 @@ struct pixel_yuv_u8 {
|
||||
* @format_pair.yuv: Same color as @format_pair.rgb, but converted to
|
||||
* YUV using @encoding and @range.
|
||||
*/
|
||||
struct yuv_u8_to_argb_u16_case {
|
||||
struct yuv_u16_to_argb_u16_case {
|
||||
enum drm_color_encoding encoding;
|
||||
enum drm_color_range range;
|
||||
size_t n_colors;
|
||||
struct format_pair {
|
||||
char *name;
|
||||
struct pixel_yuv_u8 yuv;
|
||||
struct pixel_yuv_u16 yuv;
|
||||
struct pixel_argb_u16 argb;
|
||||
} colors[TEST_BUFF_SIZE];
|
||||
};
|
||||
@@ -57,14 +57,14 @@ struct yuv_u8_to_argb_u16_case {
|
||||
* For more information got to the docs:
|
||||
* https://colour.readthedocs.io/en/master/generated/colour.RGB_to_YCbCr.html
|
||||
*/
|
||||
static struct yuv_u8_to_argb_u16_case yuv_u8_to_argb_u16_cases[] = {
|
||||
static struct yuv_u16_to_argb_u16_case yuv_u16_to_argb_u16_cases[] = {
|
||||
/*
|
||||
* colour.RGB_to_YCbCr(<rgb color in 16 bit form>,
|
||||
* K=colour.WEIGHTS_YCBCR["ITU-R BT.601"],
|
||||
* in_bits = 16,
|
||||
* in_legal = False,
|
||||
* in_int = True,
|
||||
* out_bits = 8,
|
||||
* out_bits = 16,
|
||||
* out_legal = False,
|
||||
* out_int = True)
|
||||
*
|
||||
@@ -76,13 +76,13 @@ static struct yuv_u8_to_argb_u16_case yuv_u8_to_argb_u16_cases[] = {
|
||||
.range = DRM_COLOR_YCBCR_FULL_RANGE,
|
||||
.n_colors = 6,
|
||||
.colors = {
|
||||
{ "white", { 0xff, 0x80, 0x80 }, { 0xffff, 0xffff, 0xffff, 0xffff }},
|
||||
{ "gray", { 0x80, 0x80, 0x80 }, { 0xffff, 0x8080, 0x8080, 0x8080 }},
|
||||
{ "black", { 0x00, 0x80, 0x80 }, { 0xffff, 0x0000, 0x0000, 0x0000 }},
|
||||
{ "red", { 0x4c, 0x55, 0xff }, { 0xffff, 0xffff, 0x0000, 0x0000 }},
|
||||
{ "green", { 0x96, 0x2c, 0x15 }, { 0xffff, 0x0000, 0xffff, 0x0000 }},
|
||||
{ "blue", { 0x1d, 0xff, 0x6b }, { 0xffff, 0x0000, 0x0000, 0xffff }},
|
||||
},
|
||||
{ "white", { 0xffff, 0x8000, 0x8000 }, { 0xffff, 0xffff, 0xffff, 0xffff }},
|
||||
{ "gray", { 0x8080, 0x8000, 0x8000 }, { 0xffff, 0x8080, 0x8080, 0x8080 }},
|
||||
{ "black", { 0x0000, 0x8000, 0x8000 }, { 0xffff, 0x0000, 0x0000, 0x0000 }},
|
||||
{ "red", { 0x4c8b, 0x54ce, 0xffff }, { 0xffff, 0xffff, 0x0000, 0x0000 }},
|
||||
{ "green", { 0x9645, 0x2b33, 0x14d1 }, { 0xffff, 0x0000, 0xffff, 0x0000 }},
|
||||
{ "blue", { 0x1d2f, 0xffff, 0x6b2f }, { 0xffff, 0x0000, 0x0000, 0xffff }},
|
||||
}
|
||||
},
|
||||
/*
|
||||
* colour.RGB_to_YCbCr(<rgb color in 16 bit form>,
|
||||
@@ -90,7 +90,7 @@ static struct yuv_u8_to_argb_u16_case yuv_u8_to_argb_u16_cases[] = {
|
||||
* in_bits = 16,
|
||||
* in_legal = False,
|
||||
* in_int = True,
|
||||
* out_bits = 8,
|
||||
* out_bits = 16,
|
||||
* out_legal = True,
|
||||
* out_int = True)
|
||||
* Tests cases for color conversion generated by converting RGB
|
||||
@@ -101,13 +101,13 @@ static struct yuv_u8_to_argb_u16_case yuv_u8_to_argb_u16_cases[] = {
|
||||
.range = DRM_COLOR_YCBCR_LIMITED_RANGE,
|
||||
.n_colors = 6,
|
||||
.colors = {
|
||||
{ "white", { 0xeb, 0x80, 0x80 }, { 0xffff, 0xffff, 0xffff, 0xffff }},
|
||||
{ "gray", { 0x7e, 0x80, 0x80 }, { 0xffff, 0x8080, 0x8080, 0x8080 }},
|
||||
{ "black", { 0x10, 0x80, 0x80 }, { 0xffff, 0x0000, 0x0000, 0x0000 }},
|
||||
{ "red", { 0x51, 0x5a, 0xf0 }, { 0xffff, 0xffff, 0x0000, 0x0000 }},
|
||||
{ "green", { 0x91, 0x36, 0x22 }, { 0xffff, 0x0000, 0xffff, 0x0000 }},
|
||||
{ "blue", { 0x29, 0xf0, 0x6e }, { 0xffff, 0x0000, 0x0000, 0xffff }},
|
||||
},
|
||||
{ "white", { 0xeb00, 0x8000, 0x8000 }, { 0xffff, 0xffff, 0xffff, 0xffff }},
|
||||
{ "gray", { 0x7dee, 0x8000, 0x8000 }, { 0xffff, 0x8080, 0x8080, 0x8080 }},
|
||||
{ "black", { 0x1000, 0x8000, 0x8000 }, { 0xffff, 0x0000, 0x0000, 0x0000 }},
|
||||
{ "red", { 0x517b, 0x5a34, 0xf000 }, { 0xffff, 0xffff, 0x0000, 0x0000 }},
|
||||
{ "green", { 0x908e, 0x35cc, 0x2237 }, { 0xffff, 0x0000, 0xffff, 0x0000 }},
|
||||
{ "blue", { 0x28f7, 0xf000, 0x6dc9 }, { 0xffff, 0x0000, 0x0000, 0xffff }},
|
||||
}
|
||||
},
|
||||
/*
|
||||
* colour.RGB_to_YCbCr(<rgb color in 16 bit form>,
|
||||
@@ -115,7 +115,7 @@ static struct yuv_u8_to_argb_u16_case yuv_u8_to_argb_u16_cases[] = {
|
||||
* in_bits = 16,
|
||||
* in_legal = False,
|
||||
* in_int = True,
|
||||
* out_bits = 8,
|
||||
* out_bits = 16,
|
||||
* out_legal = False,
|
||||
* out_int = True)
|
||||
* Tests cases for color conversion generated by converting RGB
|
||||
@@ -126,21 +126,21 @@ static struct yuv_u8_to_argb_u16_case yuv_u8_to_argb_u16_cases[] = {
|
||||
.range = DRM_COLOR_YCBCR_FULL_RANGE,
|
||||
.n_colors = 6,
|
||||
.colors = {
|
||||
{ "white", { 0xff, 0x80, 0x80 }, { 0xffff, 0xffff, 0xffff, 0xffff }},
|
||||
{ "gray", { 0x80, 0x80, 0x80 }, { 0xffff, 0x8080, 0x8080, 0x8080 }},
|
||||
{ "black", { 0x00, 0x80, 0x80 }, { 0xffff, 0x0000, 0x0000, 0x0000 }},
|
||||
{ "red", { 0x36, 0x63, 0xff }, { 0xffff, 0xffff, 0x0000, 0x0000 }},
|
||||
{ "green", { 0xb6, 0x1e, 0x0c }, { 0xffff, 0x0000, 0xffff, 0x0000 }},
|
||||
{ "blue", { 0x12, 0xff, 0x74 }, { 0xffff, 0x0000, 0x0000, 0xffff }},
|
||||
},
|
||||
{ "white", { 0xffff, 0x8000, 0x8000 }, { 0xffff, 0xffff, 0xffff, 0xffff }},
|
||||
{ "gray", { 0x8080, 0x8000, 0x8000 }, { 0xffff, 0x8080, 0x8080, 0x8080 }},
|
||||
{ "black", { 0x0000, 0x8000, 0x8000 }, { 0xffff, 0x0000, 0x0000, 0x0000 }},
|
||||
{ "red", { 0x366d, 0x62ac, 0xffff }, { 0xffff, 0xffff, 0x0000, 0x0000 }},
|
||||
{ "green", { 0xb717, 0x1d55, 0x0bbd }, { 0xffff, 0x0000, 0xffff, 0x0000 }},
|
||||
{ "blue", { 0x127c, 0xffff, 0x7443 }, { 0xffff, 0x0000, 0x0000, 0xffff }},
|
||||
}
|
||||
},
|
||||
/*
|
||||
* colour.RGB_to_YCbCr(<rgb color in 16 bit form>,
|
||||
* K=colour.WEIGHTS_YCBCR["ITU-R BT.709"],
|
||||
* in_bits = 16,
|
||||
* int_legal = False,
|
||||
* in_legal = False,
|
||||
* in_int = True,
|
||||
* out_bits = 8,
|
||||
* out_bits = 16,
|
||||
* out_legal = True,
|
||||
* out_int = True)
|
||||
* Tests cases for color conversion generated by converting RGB
|
||||
@@ -151,13 +151,13 @@ static struct yuv_u8_to_argb_u16_case yuv_u8_to_argb_u16_cases[] = {
|
||||
.range = DRM_COLOR_YCBCR_LIMITED_RANGE,
|
||||
.n_colors = 6,
|
||||
.colors = {
|
||||
{ "white", { 0xeb, 0x80, 0x80 }, { 0xffff, 0xffff, 0xffff, 0xffff }},
|
||||
{ "gray", { 0x7e, 0x80, 0x80 }, { 0xffff, 0x8080, 0x8080, 0x8080 }},
|
||||
{ "black", { 0x10, 0x80, 0x80 }, { 0xffff, 0x0000, 0x0000, 0x0000 }},
|
||||
{ "red", { 0x3f, 0x66, 0xf0 }, { 0xffff, 0xffff, 0x0000, 0x0000 }},
|
||||
{ "green", { 0xad, 0x2a, 0x1a }, { 0xffff, 0x0000, 0xffff, 0x0000 }},
|
||||
{ "blue", { 0x20, 0xf0, 0x76 }, { 0xffff, 0x0000, 0x0000, 0xffff }},
|
||||
},
|
||||
{ "white", { 0xeb00, 0x8000, 0x8000 }, { 0xffff, 0xffff, 0xffff, 0xffff }},
|
||||
{ "gray", { 0x7dee, 0x8000, 0x8000 }, { 0xffff, 0x8080, 0x8080, 0x8080 }},
|
||||
{ "black", { 0x1000, 0x8000, 0x8000 }, { 0xffff, 0x0000, 0x0000, 0x0000 }},
|
||||
{ "red", { 0x3e8f, 0x6656, 0xf000 }, { 0xffff, 0xffff, 0x0000, 0x0000 }},
|
||||
{ "green", { 0xaca1, 0x29aa, 0x1a45 }, { 0xffff, 0x0000, 0xffff, 0x0000 }},
|
||||
{ "blue", { 0x1fd0, 0xf000, 0x75bb }, { 0xffff, 0x0000, 0x0000, 0xffff }},
|
||||
}
|
||||
},
|
||||
/*
|
||||
* colour.RGB_to_YCbCr(<rgb color in 16 bit form>,
|
||||
@@ -165,7 +165,7 @@ static struct yuv_u8_to_argb_u16_case yuv_u8_to_argb_u16_cases[] = {
|
||||
* in_bits = 16,
|
||||
* in_legal = False,
|
||||
* in_int = True,
|
||||
* out_bits = 8,
|
||||
* out_bits = 16,
|
||||
* out_legal = False,
|
||||
* out_int = True)
|
||||
* Tests cases for color conversion generated by converting RGB
|
||||
@@ -176,13 +176,13 @@ static struct yuv_u8_to_argb_u16_case yuv_u8_to_argb_u16_cases[] = {
|
||||
.range = DRM_COLOR_YCBCR_FULL_RANGE,
|
||||
.n_colors = 6,
|
||||
.colors = {
|
||||
{ "white", { 0xff, 0x80, 0x80 }, { 0xffff, 0xffff, 0xffff, 0xffff }},
|
||||
{ "gray", { 0x80, 0x80, 0x80 }, { 0xffff, 0x8080, 0x8080, 0x8080 }},
|
||||
{ "black", { 0x00, 0x80, 0x80 }, { 0xffff, 0x0000, 0x0000, 0x0000 }},
|
||||
{ "red", { 0x43, 0x5c, 0xff }, { 0xffff, 0xffff, 0x0000, 0x0000 }},
|
||||
{ "green", { 0xad, 0x24, 0x0b }, { 0xffff, 0x0000, 0xffff, 0x0000 }},
|
||||
{ "blue", { 0x0f, 0xff, 0x76 }, { 0xffff, 0x0000, 0x0000, 0xffff }},
|
||||
},
|
||||
{ "white", { 0xffff, 0x8000, 0x8000 }, { 0xffff, 0xffff, 0xffff, 0xffff }},
|
||||
{ "gray", { 0x8080, 0x8000, 0x8000 }, { 0xffff, 0x8080, 0x8080, 0x8080 }},
|
||||
{ "black", { 0x0000, 0x8000, 0x8000 }, { 0xffff, 0x0000, 0x0000, 0x0000 }},
|
||||
{ "red", { 0x4340, 0x5c41, 0xffff }, { 0xffff, 0xffff, 0x0000, 0x0000 }},
|
||||
{ "green", { 0xad91, 0x23bf, 0x0a4c }, { 0xffff, 0x0000, 0xffff, 0x0000 }},
|
||||
{ "blue", { 0x0f2e, 0xffff, 0x75b5 }, { 0xffff, 0x0000, 0x0000, 0xffff }},
|
||||
}
|
||||
},
|
||||
/*
|
||||
* colour.RGB_to_YCbCr(<rgb color in 16 bit form>,
|
||||
@@ -190,7 +190,7 @@ static struct yuv_u8_to_argb_u16_case yuv_u8_to_argb_u16_cases[] = {
|
||||
* in_bits = 16,
|
||||
* in_legal = False,
|
||||
* in_int = True,
|
||||
* out_bits = 8,
|
||||
* out_bits = 16,
|
||||
* out_legal = True,
|
||||
* out_int = True)
|
||||
* Tests cases for color conversion generated by converting RGB
|
||||
@@ -201,32 +201,30 @@ static struct yuv_u8_to_argb_u16_case yuv_u8_to_argb_u16_cases[] = {
|
||||
.range = DRM_COLOR_YCBCR_LIMITED_RANGE,
|
||||
.n_colors = 6,
|
||||
.colors = {
|
||||
{ "white", { 0xeb, 0x80, 0x80 }, { 0xffff, 0xffff, 0xffff, 0xffff }},
|
||||
{ "gray", { 0x7e, 0x80, 0x80 }, { 0xffff, 0x8080, 0x8080, 0x8080 }},
|
||||
{ "black", { 0x10, 0x80, 0x80 }, { 0xffff, 0x0000, 0x0000, 0x0000 }},
|
||||
{ "red", { 0x4a, 0x61, 0xf0 }, { 0xffff, 0xffff, 0x0000, 0x0000 }},
|
||||
{ "green", { 0xa4, 0x2f, 0x19 }, { 0xffff, 0x0000, 0xffff, 0x0000 }},
|
||||
{ "blue", { 0x1d, 0xf0, 0x77 }, { 0xffff, 0x0000, 0x0000, 0xffff }},
|
||||
},
|
||||
{ "white", { 0xeb00, 0x8000, 0x8000 }, { 0xffff, 0xffff, 0xffff, 0xffff }},
|
||||
{ "gray", { 0x7dee, 0x8000, 0x8000 }, { 0xffff, 0x8080, 0x8080, 0x8080 }},
|
||||
{ "black", { 0x1000, 0x8000, 0x8000 }, { 0xffff, 0x0000, 0x0000, 0x0000 }},
|
||||
{ "red", { 0x4988, 0x60b9, 0xf000 }, { 0xffff, 0xffff, 0x0000, 0x0000 }},
|
||||
{ "green", { 0xa47b, 0x2f47, 0x1902 }, { 0xffff, 0x0000, 0xffff, 0x0000 }},
|
||||
{ "blue", { 0x1cfd, 0xf000, 0x76fe }, { 0xffff, 0x0000, 0x0000, 0xffff }},
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* vkms_format_test_yuv_u8_to_argb_u16 - Testing the conversion between YUV
|
||||
* vkms_format_test_yuv_u16_to_argb_u16 - Testing the conversion between YUV
|
||||
* colors to ARGB colors in VKMS
|
||||
*
|
||||
* This test will use the functions get_conversion_matrix_to_argb_u16 and
|
||||
* argb_u16_from_yuv888 to convert YUV colors (stored in
|
||||
* yuv_u8_to_argb_u16_cases) into ARGB colors.
|
||||
* argb_u16_from_yuv161616 to convert YUV colors (stored in
|
||||
* yuv_u16_to_argb_u16_cases) into ARGB colors.
|
||||
*
|
||||
* The conversion between YUV and RGB is not totally reversible, so there may be
|
||||
* some difference between the expected value and the result.
|
||||
* In addition, there may be some rounding error as the input color is 8 bits
|
||||
* and output color is 16 bits.
|
||||
*/
|
||||
static void vkms_format_test_yuv_u8_to_argb_u16(struct kunit *test)
|
||||
static void vkms_format_test_yuv_u16_to_argb_u16(struct kunit *test)
|
||||
{
|
||||
const struct yuv_u8_to_argb_u16_case *param = test->param_value;
|
||||
const struct yuv_u16_to_argb_u16_case *param = test->param_value;
|
||||
struct pixel_argb_u16 argb;
|
||||
|
||||
for (size_t i = 0; i < param->n_colors; i++) {
|
||||
@@ -236,7 +234,8 @@ static void vkms_format_test_yuv_u8_to_argb_u16(struct kunit *test)
|
||||
get_conversion_matrix_to_argb_u16
|
||||
(DRM_FORMAT_NV12, param->encoding, param->range, &matrix);
|
||||
|
||||
argb = argb_u16_from_yuv888(color->yuv.y, color->yuv.u, color->yuv.v, &matrix);
|
||||
argb = argb_u16_from_yuv161616(&matrix, color->yuv.y, color->yuv.u,
|
||||
color->yuv.v);
|
||||
|
||||
KUNIT_EXPECT_LE_MSG(test, abs_diff(argb.a, color->argb.a), 0x1ff,
|
||||
"On the A channel of the color %s expected 0x%04x, got 0x%04x",
|
||||
@@ -253,19 +252,19 @@ static void vkms_format_test_yuv_u8_to_argb_u16(struct kunit *test)
|
||||
}
|
||||
}
|
||||
|
||||
static void vkms_format_test_yuv_u8_to_argb_u16_case_desc(struct yuv_u8_to_argb_u16_case *t,
|
||||
char *desc)
|
||||
static void vkms_format_test_yuv_u16_to_argb_u16_case_desc(struct yuv_u16_to_argb_u16_case *t,
|
||||
char *desc)
|
||||
{
|
||||
snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s - %s",
|
||||
drm_get_color_encoding_name(t->encoding), drm_get_color_range_name(t->range));
|
||||
}
|
||||
|
||||
KUNIT_ARRAY_PARAM(yuv_u8_to_argb_u16, yuv_u8_to_argb_u16_cases,
|
||||
vkms_format_test_yuv_u8_to_argb_u16_case_desc
|
||||
KUNIT_ARRAY_PARAM(yuv_u16_to_argb_u16, yuv_u16_to_argb_u16_cases,
|
||||
vkms_format_test_yuv_u16_to_argb_u16_case_desc
|
||||
);
|
||||
|
||||
static struct kunit_case vkms_format_test_cases[] = {
|
||||
KUNIT_CASE_PARAM(vkms_format_test_yuv_u8_to_argb_u16, yuv_u8_to_argb_u16_gen_params),
|
||||
KUNIT_CASE_PARAM(vkms_format_test_yuv_u16_to_argb_u16, yuv_u16_to_argb_u16_gen_params),
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
@@ -259,16 +259,27 @@ static struct pixel_argb_u16 argb_u16_from_grayu16(u16 gray)
|
||||
return argb_u16_from_u16161616(0xFFFF, gray, gray, gray);
|
||||
}
|
||||
|
||||
VISIBLE_IF_KUNIT struct pixel_argb_u16 argb_u16_from_yuv888(u8 y, u8 channel_1, u8 channel_2,
|
||||
const struct conversion_matrix *matrix)
|
||||
static struct pixel_argb_u16 argb_u16_from_BGR565(const __le16 *pixel)
|
||||
{
|
||||
struct pixel_argb_u16 out_pixel;
|
||||
|
||||
out_pixel = argb_u16_from_RGB565(pixel);
|
||||
swap(out_pixel.r, out_pixel.b);
|
||||
|
||||
return out_pixel;
|
||||
}
|
||||
|
||||
VISIBLE_IF_KUNIT
|
||||
struct pixel_argb_u16 argb_u16_from_yuv161616(const struct conversion_matrix *matrix,
|
||||
u16 y, u16 channel_1, u16 channel_2)
|
||||
{
|
||||
u16 r, g, b;
|
||||
s64 fp_y, fp_channel_1, fp_channel_2;
|
||||
s64 fp_r, fp_g, fp_b;
|
||||
|
||||
fp_y = drm_int2fixp(((int)y - matrix->y_offset) * 257);
|
||||
fp_channel_1 = drm_int2fixp(((int)channel_1 - 128) * 257);
|
||||
fp_channel_2 = drm_int2fixp(((int)channel_2 - 128) * 257);
|
||||
fp_y = drm_int2fixp((int)y - matrix->y_offset * 257);
|
||||
fp_channel_1 = drm_int2fixp((int)channel_1 - 128 * 257);
|
||||
fp_channel_2 = drm_int2fixp((int)channel_2 - 128 * 257);
|
||||
|
||||
fp_r = drm_fixp_mul(matrix->matrix[0][0], fp_y) +
|
||||
drm_fixp_mul(matrix->matrix[0][1], fp_channel_1) +
|
||||
@@ -290,7 +301,65 @@ VISIBLE_IF_KUNIT struct pixel_argb_u16 argb_u16_from_yuv888(u8 y, u8 channel_1,
|
||||
|
||||
return argb_u16_from_u16161616(0xffff, r, g, b);
|
||||
}
|
||||
EXPORT_SYMBOL_IF_KUNIT(argb_u16_from_yuv888);
|
||||
EXPORT_SYMBOL_IF_KUNIT(argb_u16_from_yuv161616);
|
||||
|
||||
/**
|
||||
* READ_LINE() - Generic generator for a read_line function which can be used for format with one
|
||||
* plane and a block_h == block_w == 1.
|
||||
*
|
||||
* @function_name: Function name to generate
|
||||
* @pixel_name: Temporary pixel name used in the @__VA_ARGS__ parameters
|
||||
* @pixel_type: Used to specify the type you want to cast the pixel pointer
|
||||
* @callback: Callback to call for each pixels. This fonction should take @__VA_ARGS__ as parameter
|
||||
* and return a pixel_argb_u16
|
||||
* __VA_ARGS__: Argument to pass inside the callback. You can use @pixel_name to access current
|
||||
* pixel.
|
||||
*/
|
||||
#define READ_LINE(function_name, pixel_name, pixel_type, callback, ...) \
|
||||
static void function_name(const struct vkms_plane_state *plane, int x_start, \
|
||||
int y_start, enum pixel_read_direction direction, int count, \
|
||||
struct pixel_argb_u16 out_pixel[]) \
|
||||
{ \
|
||||
struct pixel_argb_u16 *end = out_pixel + count; \
|
||||
int step = get_block_step_bytes(plane->frame_info->fb, direction, 0); \
|
||||
u8 *src_pixels; \
|
||||
\
|
||||
packed_pixels_addr_1x1(plane->frame_info, x_start, y_start, 0, &src_pixels); \
|
||||
\
|
||||
while (out_pixel < end) { \
|
||||
pixel_type *(pixel_name) = (pixel_type *)src_pixels; \
|
||||
*out_pixel = (callback)(__VA_ARGS__); \
|
||||
out_pixel += 1; \
|
||||
src_pixels += step; \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* READ_LINE_ARGB8888() - Generic generator for ARGB8888 formats.
|
||||
* The pixel type used is u8, so pixel_name[0]..pixel_name[n] are the n components of the pixel.
|
||||
*
|
||||
* @function_name: Function name to generate
|
||||
* @pixel_name: temporary pixel to use in @a, @r, @g and @b parameters
|
||||
* @a: alpha value
|
||||
* @r: red value
|
||||
* @g: green value
|
||||
* @b: blue value
|
||||
*/
|
||||
#define READ_LINE_ARGB8888(function_name, pixel_name, a, r, g, b) \
|
||||
READ_LINE(function_name, pixel_name, u8, argb_u16_from_u8888, a, r, g, b)
|
||||
/**
|
||||
* READ_LINE_le16161616() - Generic generator for ARGB16161616 formats.
|
||||
* The pixel type used is u16, so pixel_name[0]..pixel_name[n] are the n components of the pixel.
|
||||
*
|
||||
* @function_name: Function name to generate
|
||||
* @pixel_name: temporary pixel to use in @a, @r, @g and @b parameters
|
||||
* @a: alpha value
|
||||
* @r: red value
|
||||
* @g: green value
|
||||
* @b: blue value
|
||||
*/
|
||||
#define READ_LINE_le16161616(function_name, pixel_name, a, r, g, b) \
|
||||
READ_LINE(function_name, pixel_name, __le16, argb_u16_from_le16161616, a, r, g, b)
|
||||
|
||||
/*
|
||||
* The following functions are read_line function for each pixel format supported by VKMS.
|
||||
@@ -378,138 +447,27 @@ static void R4_read_line(const struct vkms_plane_state *plane, int x_start,
|
||||
Rx_read_line(plane, x_start, y_start, direction, count, out_pixel);
|
||||
}
|
||||
|
||||
static void R8_read_line(const struct vkms_plane_state *plane, int x_start,
|
||||
int y_start, enum pixel_read_direction direction, int count,
|
||||
struct pixel_argb_u16 out_pixel[])
|
||||
{
|
||||
struct pixel_argb_u16 *end = out_pixel + count;
|
||||
u8 *src_pixels;
|
||||
int step = get_block_step_bytes(plane->frame_info->fb, direction, 0);
|
||||
|
||||
packed_pixels_addr_1x1(plane->frame_info, x_start, y_start, 0, &src_pixels);
|
||||
READ_LINE_ARGB8888(XRGB8888_read_line, px, 0xFF, px[2], px[1], px[0])
|
||||
READ_LINE_ARGB8888(XBGR8888_read_line, px, 0xFF, px[0], px[1], px[2])
|
||||
|
||||
while (out_pixel < end) {
|
||||
*out_pixel = argb_u16_from_gray8(*src_pixels);
|
||||
src_pixels += step;
|
||||
out_pixel += 1;
|
||||
}
|
||||
}
|
||||
READ_LINE_ARGB8888(ARGB8888_read_line, px, px[3], px[2], px[1], px[0])
|
||||
READ_LINE_ARGB8888(ABGR8888_read_line, px, px[3], px[0], px[1], px[2])
|
||||
READ_LINE_ARGB8888(RGBA8888_read_line, px, px[0], px[3], px[2], px[1])
|
||||
READ_LINE_ARGB8888(BGRA8888_read_line, px, px[0], px[1], px[2], px[3])
|
||||
|
||||
static void ARGB8888_read_line(const struct vkms_plane_state *plane, int x_start, int y_start,
|
||||
enum pixel_read_direction direction, int count,
|
||||
struct pixel_argb_u16 out_pixel[])
|
||||
{
|
||||
struct pixel_argb_u16 *end = out_pixel + count;
|
||||
u8 *src_pixels;
|
||||
READ_LINE_ARGB8888(RGB888_read_line, px, 0xFF, px[2], px[1], px[0])
|
||||
READ_LINE_ARGB8888(BGR888_read_line, px, 0xFF, px[0], px[1], px[2])
|
||||
|
||||
packed_pixels_addr_1x1(plane->frame_info, x_start, y_start, 0, &src_pixels);
|
||||
READ_LINE_le16161616(ARGB16161616_read_line, px, px[3], px[2], px[1], px[0])
|
||||
READ_LINE_le16161616(ABGR16161616_read_line, px, px[3], px[0], px[1], px[2])
|
||||
READ_LINE_le16161616(XRGB16161616_read_line, px, cpu_to_le16(0xFFFF), px[2], px[1], px[0])
|
||||
READ_LINE_le16161616(XBGR16161616_read_line, px, cpu_to_le16(0xFFFF), px[0], px[1], px[2])
|
||||
|
||||
int step = get_block_step_bytes(plane->frame_info->fb, direction, 0);
|
||||
READ_LINE(RGB565_read_line, px, __le16, argb_u16_from_RGB565, px)
|
||||
READ_LINE(BGR565_read_line, px, __le16, argb_u16_from_BGR565, px)
|
||||
|
||||
while (out_pixel < end) {
|
||||
u8 *px = (u8 *)src_pixels;
|
||||
*out_pixel = argb_u16_from_u8888(px[3], px[2], px[1], px[0]);
|
||||
out_pixel += 1;
|
||||
src_pixels += step;
|
||||
}
|
||||
}
|
||||
|
||||
static void XRGB8888_read_line(const struct vkms_plane_state *plane, int x_start, int y_start,
|
||||
enum pixel_read_direction direction, int count,
|
||||
struct pixel_argb_u16 out_pixel[])
|
||||
{
|
||||
struct pixel_argb_u16 *end = out_pixel + count;
|
||||
u8 *src_pixels;
|
||||
|
||||
packed_pixels_addr_1x1(plane->frame_info, x_start, y_start, 0, &src_pixels);
|
||||
|
||||
int step = get_block_step_bytes(plane->frame_info->fb, direction, 0);
|
||||
|
||||
while (out_pixel < end) {
|
||||
u8 *px = (u8 *)src_pixels;
|
||||
*out_pixel = argb_u16_from_u8888(255, px[2], px[1], px[0]);
|
||||
out_pixel += 1;
|
||||
src_pixels += step;
|
||||
}
|
||||
}
|
||||
|
||||
static void ABGR8888_read_line(const struct vkms_plane_state *plane, int x_start, int y_start,
|
||||
enum pixel_read_direction direction, int count,
|
||||
struct pixel_argb_u16 out_pixel[])
|
||||
{
|
||||
struct pixel_argb_u16 *end = out_pixel + count;
|
||||
u8 *src_pixels;
|
||||
|
||||
packed_pixels_addr_1x1(plane->frame_info, x_start, y_start, 0, &src_pixels);
|
||||
|
||||
int step = get_block_step_bytes(plane->frame_info->fb, direction, 0);
|
||||
|
||||
while (out_pixel < end) {
|
||||
u8 *px = (u8 *)src_pixels;
|
||||
/* Switch blue and red pixels. */
|
||||
*out_pixel = argb_u16_from_u8888(px[3], px[0], px[1], px[2]);
|
||||
out_pixel += 1;
|
||||
src_pixels += step;
|
||||
}
|
||||
}
|
||||
|
||||
static void ARGB16161616_read_line(const struct vkms_plane_state *plane, int x_start,
|
||||
int y_start, enum pixel_read_direction direction, int count,
|
||||
struct pixel_argb_u16 out_pixel[])
|
||||
{
|
||||
struct pixel_argb_u16 *end = out_pixel + count;
|
||||
u8 *src_pixels;
|
||||
|
||||
packed_pixels_addr_1x1(plane->frame_info, x_start, y_start, 0, &src_pixels);
|
||||
|
||||
int step = get_block_step_bytes(plane->frame_info->fb, direction, 0);
|
||||
|
||||
while (out_pixel < end) {
|
||||
u16 *px = (u16 *)src_pixels;
|
||||
*out_pixel = argb_u16_from_u16161616(px[3], px[2], px[1], px[0]);
|
||||
out_pixel += 1;
|
||||
src_pixels += step;
|
||||
}
|
||||
}
|
||||
|
||||
static void XRGB16161616_read_line(const struct vkms_plane_state *plane, int x_start,
|
||||
int y_start, enum pixel_read_direction direction, int count,
|
||||
struct pixel_argb_u16 out_pixel[])
|
||||
{
|
||||
struct pixel_argb_u16 *end = out_pixel + count;
|
||||
u8 *src_pixels;
|
||||
|
||||
packed_pixels_addr_1x1(plane->frame_info, x_start, y_start, 0, &src_pixels);
|
||||
|
||||
int step = get_block_step_bytes(plane->frame_info->fb, direction, 0);
|
||||
|
||||
while (out_pixel < end) {
|
||||
__le16 *px = (__le16 *)src_pixels;
|
||||
*out_pixel = argb_u16_from_le16161616(cpu_to_le16(0xFFFF), px[2], px[1], px[0]);
|
||||
out_pixel += 1;
|
||||
src_pixels += step;
|
||||
}
|
||||
}
|
||||
|
||||
static void RGB565_read_line(const struct vkms_plane_state *plane, int x_start,
|
||||
int y_start, enum pixel_read_direction direction, int count,
|
||||
struct pixel_argb_u16 out_pixel[])
|
||||
{
|
||||
struct pixel_argb_u16 *end = out_pixel + count;
|
||||
u8 *src_pixels;
|
||||
|
||||
packed_pixels_addr_1x1(plane->frame_info, x_start, y_start, 0, &src_pixels);
|
||||
|
||||
int step = get_block_step_bytes(plane->frame_info->fb, direction, 0);
|
||||
|
||||
while (out_pixel < end) {
|
||||
__le16 *px = (__le16 *)src_pixels;
|
||||
|
||||
*out_pixel = argb_u16_from_RGB565(px);
|
||||
out_pixel += 1;
|
||||
src_pixels += step;
|
||||
}
|
||||
}
|
||||
READ_LINE(R8_read_line, px, u8, argb_u16_from_gray8, *px)
|
||||
|
||||
/*
|
||||
* This callback can be used for YUV formats where U and V values are
|
||||
@@ -521,35 +479,57 @@ static void RGB565_read_line(const struct vkms_plane_state *plane, int x_start,
|
||||
* - Convert YUV and YVU with the same function (a column swap is needed when setting up
|
||||
* plane->conversion_matrix)
|
||||
*/
|
||||
static void semi_planar_yuv_read_line(const struct vkms_plane_state *plane, int x_start,
|
||||
int y_start, enum pixel_read_direction direction, int count,
|
||||
struct pixel_argb_u16 out_pixel[])
|
||||
{
|
||||
u8 *y_plane;
|
||||
u8 *uv_plane;
|
||||
|
||||
packed_pixels_addr_1x1(plane->frame_info, x_start, y_start, 0,
|
||||
&y_plane);
|
||||
packed_pixels_addr_1x1(plane->frame_info,
|
||||
x_start / plane->frame_info->fb->format->hsub,
|
||||
y_start / plane->frame_info->fb->format->vsub, 1,
|
||||
&uv_plane);
|
||||
int step_y = get_block_step_bytes(plane->frame_info->fb, direction, 0);
|
||||
int step_uv = get_block_step_bytes(plane->frame_info->fb, direction, 1);
|
||||
int subsampling = get_subsampling(plane->frame_info->fb->format, direction);
|
||||
int subsampling_offset = get_subsampling_offset(direction, x_start, y_start);
|
||||
const struct conversion_matrix *conversion_matrix = &plane->conversion_matrix;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
*out_pixel = argb_u16_from_yuv888(y_plane[0], uv_plane[0], uv_plane[1],
|
||||
conversion_matrix);
|
||||
out_pixel += 1;
|
||||
y_plane += step_y;
|
||||
if ((i + subsampling_offset + 1) % subsampling == 0)
|
||||
uv_plane += step_uv;
|
||||
}
|
||||
/**
|
||||
* READ_LINE_YUV_SEMIPLANAR() - Generic generator for a read_line function which can be used for yuv
|
||||
* formats with two planes and block_w == block_h == 1.
|
||||
*
|
||||
* @function_name: Function name to generate
|
||||
* @pixel_1_name: temporary pixel name for the first plane used in the @__VA_ARGS__ parameters
|
||||
* @pixel_2_name: temporary pixel name for the second plane used in the @__VA_ARGS__ parameters
|
||||
* @pixel_1_type: Used to specify the type you want to cast the pixel pointer on the plane 1
|
||||
* @pixel_2_type: Used to specify the type you want to cast the pixel pointer on the plane 2
|
||||
* @callback: Callback to call for each pixels. This function should take
|
||||
* (struct conversion_matrix*, @__VA_ARGS__) as parameter and return a pixel_argb_u16
|
||||
* __VA_ARGS__: Argument to pass inside the callback. You can use @pixel_1_name and @pixel_2_name
|
||||
* to access current pixel values
|
||||
*/
|
||||
#define READ_LINE_YUV_SEMIPLANAR(function_name, pixel_1_name, pixel_2_name, pixel_1_type, \
|
||||
pixel_2_type, callback, ...) \
|
||||
static void function_name(const struct vkms_plane_state *plane, int x_start, \
|
||||
int y_start, enum pixel_read_direction direction, int count, \
|
||||
struct pixel_argb_u16 out_pixel[]) \
|
||||
{ \
|
||||
u8 *plane_1; \
|
||||
u8 *plane_2; \
|
||||
\
|
||||
packed_pixels_addr_1x1(plane->frame_info, x_start, y_start, 0, \
|
||||
&plane_1); \
|
||||
packed_pixels_addr_1x1(plane->frame_info, \
|
||||
x_start / plane->frame_info->fb->format->hsub, \
|
||||
y_start / plane->frame_info->fb->format->vsub, 1, \
|
||||
&plane_2); \
|
||||
int step_1 = get_block_step_bytes(plane->frame_info->fb, direction, 0); \
|
||||
int step_2 = get_block_step_bytes(plane->frame_info->fb, direction, 1); \
|
||||
int subsampling = get_subsampling(plane->frame_info->fb->format, direction); \
|
||||
int subsampling_offset = get_subsampling_offset(direction, x_start, y_start); \
|
||||
const struct conversion_matrix *conversion_matrix = &plane->conversion_matrix; \
|
||||
\
|
||||
for (int i = 0; i < count; i++) { \
|
||||
pixel_1_type *(pixel_1_name) = (pixel_1_type *)plane_1; \
|
||||
pixel_2_type *(pixel_2_name) = (pixel_2_type *)plane_2; \
|
||||
*out_pixel = (callback)(conversion_matrix, __VA_ARGS__); \
|
||||
out_pixel += 1; \
|
||||
plane_1 += step_1; \
|
||||
if ((i + subsampling_offset + 1) % subsampling == 0) \
|
||||
plane_2 += step_2; \
|
||||
} \
|
||||
}
|
||||
|
||||
READ_LINE_YUV_SEMIPLANAR(YUV888_semiplanar_read_line, y, uv, u8, u8, argb_u16_from_yuv161616,
|
||||
y[0] * 257, uv[0] * 257, uv[1] * 257)
|
||||
READ_LINE_YUV_SEMIPLANAR(YUV161616_semiplanar_read_line, y, uv, u16, u16, argb_u16_from_yuv161616,
|
||||
y[0], uv[0], uv[1])
|
||||
/*
|
||||
* This callback can be used for YUV format where each color component is
|
||||
* stored in a different plane (often called planar formats). It will
|
||||
@@ -586,8 +566,9 @@ static void planar_yuv_read_line(const struct vkms_plane_state *plane, int x_sta
|
||||
const struct conversion_matrix *conversion_matrix = &plane->conversion_matrix;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
*out_pixel = argb_u16_from_yuv888(*y_plane, *channel_1_plane, *channel_2_plane,
|
||||
conversion_matrix);
|
||||
*out_pixel = argb_u16_from_yuv161616(conversion_matrix,
|
||||
*y_plane * 257, *channel_1_plane * 257,
|
||||
*channel_2_plane * 257);
|
||||
out_pixel += 1;
|
||||
y_plane += step_y;
|
||||
if ((i + subsampling_offset + 1) % subsampling == 0) {
|
||||
@@ -712,23 +693,43 @@ pixel_read_line_t get_pixel_read_line_function(u32 format)
|
||||
switch (format) {
|
||||
case DRM_FORMAT_ARGB8888:
|
||||
return &ARGB8888_read_line;
|
||||
case DRM_FORMAT_XRGB8888:
|
||||
return &XRGB8888_read_line;
|
||||
case DRM_FORMAT_ABGR8888:
|
||||
return &ABGR8888_read_line;
|
||||
case DRM_FORMAT_BGRA8888:
|
||||
return &BGRA8888_read_line;
|
||||
case DRM_FORMAT_RGBA8888:
|
||||
return &RGBA8888_read_line;
|
||||
case DRM_FORMAT_XRGB8888:
|
||||
return &XRGB8888_read_line;
|
||||
case DRM_FORMAT_XBGR8888:
|
||||
return &XBGR8888_read_line;
|
||||
case DRM_FORMAT_RGB888:
|
||||
return &RGB888_read_line;
|
||||
case DRM_FORMAT_BGR888:
|
||||
return &BGR888_read_line;
|
||||
case DRM_FORMAT_ARGB16161616:
|
||||
return &ARGB16161616_read_line;
|
||||
case DRM_FORMAT_ABGR16161616:
|
||||
return &ABGR16161616_read_line;
|
||||
case DRM_FORMAT_XRGB16161616:
|
||||
return &XRGB16161616_read_line;
|
||||
case DRM_FORMAT_XBGR16161616:
|
||||
return &XBGR16161616_read_line;
|
||||
case DRM_FORMAT_RGB565:
|
||||
return &RGB565_read_line;
|
||||
case DRM_FORMAT_BGR565:
|
||||
return &BGR565_read_line;
|
||||
case DRM_FORMAT_NV12:
|
||||
case DRM_FORMAT_NV16:
|
||||
case DRM_FORMAT_NV24:
|
||||
case DRM_FORMAT_NV21:
|
||||
case DRM_FORMAT_NV61:
|
||||
case DRM_FORMAT_NV42:
|
||||
return &semi_planar_yuv_read_line;
|
||||
return &YUV888_semiplanar_read_line;
|
||||
case DRM_FORMAT_P010:
|
||||
case DRM_FORMAT_P012:
|
||||
case DRM_FORMAT_P016:
|
||||
return &YUV161616_semiplanar_read_line;
|
||||
case DRM_FORMAT_YUV420:
|
||||
case DRM_FORMAT_YUV422:
|
||||
case DRM_FORMAT_YUV444:
|
||||
|
||||
@@ -14,8 +14,8 @@ void get_conversion_matrix_to_argb_u16(u32 format, enum drm_color_encoding encod
|
||||
struct conversion_matrix *matrix);
|
||||
|
||||
#if IS_ENABLED(CONFIG_KUNIT)
|
||||
struct pixel_argb_u16 argb_u16_from_yuv888(u8 y, u8 channel_1, u8 channel_2,
|
||||
const struct conversion_matrix *matrix);
|
||||
struct pixel_argb_u16 argb_u16_from_yuv161616(const struct conversion_matrix *matrix,
|
||||
u16 y, u16 channel_1, u16 channel_2);
|
||||
#endif
|
||||
|
||||
#endif /* _VKMS_FORMATS_H_ */
|
||||
|
||||
@@ -14,11 +14,19 @@
|
||||
|
||||
static const u32 vkms_formats[] = {
|
||||
DRM_FORMAT_ARGB8888,
|
||||
DRM_FORMAT_XRGB8888,
|
||||
DRM_FORMAT_ABGR8888,
|
||||
DRM_FORMAT_BGRA8888,
|
||||
DRM_FORMAT_RGBA8888,
|
||||
DRM_FORMAT_XRGB8888,
|
||||
DRM_FORMAT_XBGR8888,
|
||||
DRM_FORMAT_RGB888,
|
||||
DRM_FORMAT_BGR888,
|
||||
DRM_FORMAT_XRGB16161616,
|
||||
DRM_FORMAT_XBGR16161616,
|
||||
DRM_FORMAT_ARGB16161616,
|
||||
DRM_FORMAT_ABGR16161616,
|
||||
DRM_FORMAT_RGB565,
|
||||
DRM_FORMAT_BGR565,
|
||||
DRM_FORMAT_NV12,
|
||||
DRM_FORMAT_NV16,
|
||||
DRM_FORMAT_NV24,
|
||||
@@ -31,6 +39,9 @@ static const u32 vkms_formats[] = {
|
||||
DRM_FORMAT_YVU420,
|
||||
DRM_FORMAT_YVU422,
|
||||
DRM_FORMAT_YVU444,
|
||||
DRM_FORMAT_P010,
|
||||
DRM_FORMAT_P012,
|
||||
DRM_FORMAT_P016,
|
||||
DRM_FORMAT_R1,
|
||||
DRM_FORMAT_R2,
|
||||
DRM_FORMAT_R4,
|
||||
|
||||
@@ -191,10 +191,22 @@ struct dma_buf *xe_gem_prime_export(struct drm_gem_object *obj, int flags)
|
||||
{
|
||||
struct xe_bo *bo = gem_to_xe_bo(obj);
|
||||
struct dma_buf *buf;
|
||||
struct ttm_operation_ctx ctx = {
|
||||
.interruptible = true,
|
||||
.no_wait_gpu = true,
|
||||
/* We opt to avoid OOM on system pages allocations */
|
||||
.gfp_retry_mayfail = true,
|
||||
.allow_res_evict = false,
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (bo->vm)
|
||||
return ERR_PTR(-EPERM);
|
||||
|
||||
ret = ttm_bo_setup_export(&bo->ttm, &ctx);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
buf = drm_gem_prime_export(obj, flags);
|
||||
if (!IS_ERR(buf))
|
||||
buf->ops = &xe_dmabuf_ops;
|
||||
|
||||
@@ -556,34 +556,13 @@ EXPORT_SYMBOL(vga_put);
|
||||
|
||||
static bool vga_is_firmware_default(struct pci_dev *pdev)
|
||||
{
|
||||
#if defined(CONFIG_X86)
|
||||
u64 base = screen_info.lfb_base;
|
||||
u64 size = screen_info.lfb_size;
|
||||
struct resource *r;
|
||||
u64 limit;
|
||||
#ifdef CONFIG_SCREEN_INFO
|
||||
struct screen_info *si = &screen_info;
|
||||
|
||||
/* Select the device owning the boot framebuffer if there is one */
|
||||
|
||||
if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
|
||||
base |= (u64)screen_info.ext_lfb_base << 32;
|
||||
|
||||
limit = base + size;
|
||||
|
||||
/* Does firmware framebuffer belong to us? */
|
||||
pci_dev_for_each_resource(pdev, r) {
|
||||
if (resource_type(r) != IORESOURCE_MEM)
|
||||
continue;
|
||||
|
||||
if (!r->start || !r->end)
|
||||
continue;
|
||||
|
||||
if (base < r->start || limit >= r->end)
|
||||
continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return pdev == screen_info_pci_dev(si);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool vga_arb_integrated_gpu(struct device *dev)
|
||||
|
||||
@@ -466,6 +466,8 @@ pgprot_t ttm_io_prot(struct ttm_buffer_object *bo, struct ttm_resource *res,
|
||||
void ttm_bo_tt_destroy(struct ttm_buffer_object *bo);
|
||||
int ttm_bo_populate(struct ttm_buffer_object *bo,
|
||||
struct ttm_operation_ctx *ctx);
|
||||
int ttm_bo_setup_export(struct ttm_buffer_object *bo,
|
||||
struct ttm_operation_ctx *ctx);
|
||||
|
||||
/* Driver LRU walk helpers initially targeted for shrinking. */
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ enum amdxdna_drm_ioctl_id {
|
||||
DRM_AMDXDNA_EXEC_CMD,
|
||||
DRM_AMDXDNA_GET_INFO,
|
||||
DRM_AMDXDNA_SET_STATE,
|
||||
DRM_AMDXDNA_GET_ARRAY = 10,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -455,6 +456,112 @@ struct amdxdna_drm_get_info {
|
||||
__u64 buffer; /* in/out */
|
||||
};
|
||||
|
||||
#define AMDXDNA_HWCTX_STATE_IDLE 0
|
||||
#define AMDXDNA_HWCTX_STATE_ACTIVE 1
|
||||
|
||||
/**
|
||||
* struct amdxdna_drm_hwctx_entry - The hardware context array entry
|
||||
*/
|
||||
struct amdxdna_drm_hwctx_entry {
|
||||
/** @context_id: Context ID. */
|
||||
__u32 context_id;
|
||||
/** @start_col: Start AIE array column assigned to context. */
|
||||
__u32 start_col;
|
||||
/** @num_col: Number of AIE array columns assigned to context. */
|
||||
__u32 num_col;
|
||||
/** @hwctx_id: The real hardware context id. */
|
||||
__u32 hwctx_id;
|
||||
/** @pid: ID of process which created this context. */
|
||||
__s64 pid;
|
||||
/** @command_submissions: Number of commands submitted. */
|
||||
__u64 command_submissions;
|
||||
/** @command_completions: Number of commands completed. */
|
||||
__u64 command_completions;
|
||||
/** @migrations: Number of times been migrated. */
|
||||
__u64 migrations;
|
||||
/** @preemptions: Number of times been preempted. */
|
||||
__u64 preemptions;
|
||||
/** @errors: Number of errors happened. */
|
||||
__u64 errors;
|
||||
/** @priority: Context priority. */
|
||||
__u64 priority;
|
||||
/** @heap_usage: Usage of device heap buffer. */
|
||||
__u64 heap_usage;
|
||||
/** @suspensions: Number of times been suspended. */
|
||||
__u64 suspensions;
|
||||
/**
|
||||
* @state: Context state.
|
||||
* %AMDXDNA_HWCTX_STATE_IDLE
|
||||
* %AMDXDNA_HWCTX_STATE_ACTIVE
|
||||
*/
|
||||
__u32 state;
|
||||
/** @pasid: PASID been bound. */
|
||||
__u32 pasid;
|
||||
/** @gops: Giga operations per second. */
|
||||
__u32 gops;
|
||||
/** @fps: Frames per second. */
|
||||
__u32 fps;
|
||||
/** @dma_bandwidth: DMA bandwidth. */
|
||||
__u32 dma_bandwidth;
|
||||
/** @latency: Frame response latency. */
|
||||
__u32 latency;
|
||||
/** @frame_exec_time: Frame execution time. */
|
||||
__u32 frame_exec_time;
|
||||
/** @txn_op_idx: Index of last control code executed. */
|
||||
__u32 txn_op_idx;
|
||||
/** @ctx_pc: Program counter. */
|
||||
__u32 ctx_pc;
|
||||
/** @fatal_error_type: Fatal error type if context crashes. */
|
||||
__u32 fatal_error_type;
|
||||
/** @fatal_error_exception_type: Firmware exception type. */
|
||||
__u32 fatal_error_exception_type;
|
||||
/** @fatal_error_exception_pc: Firmware exception program counter. */
|
||||
__u32 fatal_error_exception_pc;
|
||||
/** @fatal_error_app_module: Exception module name. */
|
||||
__u32 fatal_error_app_module;
|
||||
/** @pad: Structure pad. */
|
||||
__u32 pad;
|
||||
};
|
||||
|
||||
#define DRM_AMDXDNA_HW_CONTEXT_ALL 0
|
||||
|
||||
/**
|
||||
* struct amdxdna_drm_get_array - Get information array.
|
||||
*/
|
||||
struct amdxdna_drm_get_array {
|
||||
/**
|
||||
* @param:
|
||||
*
|
||||
* Supported params:
|
||||
*
|
||||
* %DRM_AMDXDNA_HW_CONTEXT_ALL:
|
||||
* Returns all created hardware contexts.
|
||||
*/
|
||||
__u32 param;
|
||||
/**
|
||||
* @element_size:
|
||||
*
|
||||
* Specifies maximum element size and returns the actual element size.
|
||||
*/
|
||||
__u32 element_size;
|
||||
/**
|
||||
* @num_element:
|
||||
*
|
||||
* Specifies maximum number of elements and returns the actual number
|
||||
* of elements.
|
||||
*/
|
||||
__u32 num_element; /* in/out */
|
||||
/** @pad: MBZ */
|
||||
__u32 pad;
|
||||
/**
|
||||
* @buffer:
|
||||
*
|
||||
* Specifies the match conditions and returns the matched information
|
||||
* array.
|
||||
*/
|
||||
__u64 buffer;
|
||||
};
|
||||
|
||||
enum amdxdna_drm_set_param {
|
||||
DRM_AMDXDNA_SET_POWER_MODE,
|
||||
DRM_AMDXDNA_WRITE_AIE_MEM,
|
||||
@@ -519,6 +626,10 @@ struct amdxdna_drm_set_power_mode {
|
||||
DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDXDNA_SET_STATE, \
|
||||
struct amdxdna_drm_set_state)
|
||||
|
||||
#define DRM_IOCTL_AMDXDNA_GET_ARRAY \
|
||||
DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDXDNA_GET_ARRAY, \
|
||||
struct amdxdna_drm_get_array)
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern c end */
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user