mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-23 20:24:12 +08:00
drm-misc-next for v6.3:
UAPI Changes: * fourcc: Document Open Source user waiver Cross-subsystem Changes: * firmware: fix color-format selection for system framebuffers Core Changes: * format-helper: Add conversion from XRGB8888 to various sysfb formats; Make XRGB8888 the only driver-emulated legacy format * fb-helper: Avoid blank consoles from selecting an incorrect color format * probe-helper: Enable/disable HPD on connectors plus driver updates * Use drm_dbg_ helpers in several places * docs: Document defaults for CRTC backgrounds; Document use of drm_minor Driver Changes: * arm/hdlcd: Use new debugfs helpers * gud: Use new debugfs helpers * panel: Support Visionox VTDR6130 AMOLED DSI; Support Himax HX8394; Convert many drivers to common generic DSI write-sequence helper * v3d: Do not opencode drm_gem_object_lookup() * vc4: Various HVS an CRTC fixes * vkms: Fix SEGFAULT from incorrect GEM-buffer mapping * Convert various drivers to i2c probe_new() -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEchf7rIzpz2NEoWjlaA3BHVMLeiMFAmPAA0AACgkQaA3BHVML eiMKNAgAoXCFd7YMKoHSDlmAOztP+0qdZWM1LkpyC3fTpYbbNC1xI8yn7TVZIbgY qtkceCUAGmzuO5kTo0aSZdgPWvdWCuDmYBQsX/VwACchSA0aOKZcCaqXGi2Y39D6 G4xsHJyRhU/lWzn/GZQ4+l46m6NAlnrLFBfuLlOHDhYtYZq9D8gXEDm7NSl8/HGF OjtfSFINKKtOCjvi5GAa8CfnE8GVp59paFKJuj8xU6Dqqlorff+XroWkQG8LV4qi 3UyShQL6d/2hiRQ7fIhXEGCKit7rJkEpfsLvSqJkTkzOKyjhnIZbJIuesgqhtbEH OpWsmUVKNphi0Y5zw5ZiTqrSy0Py7g== =+mHi -----END PGP SIGNATURE----- Merge tag 'drm-misc-next-2023-01-12' of git://anongit.freedesktop.org/drm/drm-misc into drm-next drm-misc-next for v6.3: UAPI Changes: * fourcc: Document Open Source user waiver Cross-subsystem Changes: * firmware: fix color-format selection for system framebuffers Core Changes: * format-helper: Add conversion from XRGB8888 to various sysfb formats; Make XRGB8888 the only driver-emulated legacy format * fb-helper: Avoid blank consoles from selecting an incorrect color format * probe-helper: Enable/disable HPD on connectors plus driver updates * Use drm_dbg_ helpers in several places * docs: Document defaults for CRTC backgrounds; Document use of drm_minor Driver Changes: * arm/hdlcd: Use new debugfs helpers * gud: Use new debugfs helpers * panel: Support Visionox VTDR6130 AMOLED DSI; Support Himax HX8394; Convert many drivers to common generic DSI write-sequence helper * v3d: Do not opencode drm_gem_object_lookup() * vc4: Various HVS an CRTC fixes * vkms: Fix SEGFAULT from incorrect GEM-buffer mapping * Convert various drivers to i2c probe_new() Signed-off-by: Dave Airlie <airlied@redhat.com> From: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/Y8ADeSzZDj+tpibF@linux-uq9g
This commit is contained in:
commit
c37ea39c1f
@ -0,0 +1,76 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only or BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/himax,hx8394.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Himax HX8394 MIPI-DSI LCD panel controller
|
||||
|
||||
maintainers:
|
||||
- Ondrej Jirman <megi@xff.cz>
|
||||
- Javier Martinez Canillas <javierm@redhat.com>
|
||||
|
||||
description:
|
||||
Device tree bindings for panels based on the Himax HX8394 controller,
|
||||
such as the HannStar HSD060BHW4 720x1440 TFT LCD panel connected with
|
||||
a MIPI-DSI video interface.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- hannstar,hsd060bhw4
|
||||
- const: himax,hx8394
|
||||
|
||||
reg: true
|
||||
|
||||
reset-gpios: true
|
||||
|
||||
backlight: true
|
||||
|
||||
port: true
|
||||
|
||||
vcc-supply:
|
||||
description: Panel power supply
|
||||
|
||||
iovcc-supply:
|
||||
description: I/O voltage supply
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reset-gpios
|
||||
- backlight
|
||||
- port
|
||||
- vcc-supply
|
||||
- iovcc-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
panel@0 {
|
||||
compatible = "hannstar,hsd060bhw4", "himax,hx8394";
|
||||
reg = <0>;
|
||||
vcc-supply = <®_2v8_p>;
|
||||
iovcc-supply = <®_1v8_p>;
|
||||
reset-gpios = <&gpio3 13 GPIO_ACTIVE_LOW>;
|
||||
backlight = <&backlight>;
|
||||
|
||||
port {
|
||||
mipi_in_panel: endpoint {
|
||||
remote-endpoint = <&mipi_out_panel>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -0,0 +1,53 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/visionox,vtdr6130.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Visionox VTDR6130 AMOLED DSI Panel
|
||||
|
||||
maintainers:
|
||||
- Neil Armstrong <neil.armstrong@linaro.org>
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: visionox,vtdr6130
|
||||
|
||||
vddio-supply: true
|
||||
vci-supply: true
|
||||
vdd-supply: true
|
||||
port: true
|
||||
reset-gpios: true
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- vddio-supply
|
||||
- vci-supply
|
||||
- vdd-supply
|
||||
- reset-gpios
|
||||
- port
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
panel {
|
||||
compatible = "visionox,vtdr6130";
|
||||
|
||||
vddio-supply = <&vreg_l12b_1p8>;
|
||||
vci-supply = <&vreg_l13b_3p0>;
|
||||
vdd-supply = <&vreg_l11b_1p2>;
|
||||
|
||||
reset-gpios = <&tlmm 133 GPIO_ACTIVE_LOW>;
|
||||
|
||||
port {
|
||||
panel0_in: endpoint {
|
||||
remote-endpoint = <&dsi0_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
@ -222,6 +222,7 @@ Code Seq# Include File Comments
|
||||
'a' 00-0F drivers/crypto/qat/qat_common/adf_cfg_common.h conflict! qat driver
|
||||
'b' 00-FF conflict! bit3 vme host bridge
|
||||
<mailto:natalia@nikhefk.nikhef.nl>
|
||||
'b' 00-0F linux/dma-buf.h conflict!
|
||||
'c' all linux/cm4000_cs.h conflict!
|
||||
'c' 00-7F linux/comstats.h conflict!
|
||||
'c' 00-7F linux/coda.h conflict!
|
||||
|
@ -6550,6 +6550,14 @@ S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
F: drivers/gpu/drm/tiny/gm12u320.c
|
||||
|
||||
DRM DRIVER FOR HIMAX HX8394 MIPI-DSI LCD panels
|
||||
M: Ondrej Jirman <megi@xff.cz>
|
||||
M: Javier Martinez Canillas <javierm@redhat.com>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
F: Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml
|
||||
F: drivers/gpu/drm/panel/panel-himax-hx8394.c
|
||||
|
||||
DRM DRIVER FOR HX8357D PANELS
|
||||
M: Emma Anholt <emma@anholt.net>
|
||||
S: Maintained
|
||||
@ -7009,7 +7017,6 @@ M: Xinliang Liu <xinliang.liu@linaro.org>
|
||||
M: Tian Tao <tiantao6@hisilicon.com>
|
||||
R: John Stultz <jstultz@google.com>
|
||||
R: Xinwei Kong <kong.kongxinwei@hisilicon.com>
|
||||
R: Chen Feng <puck.chen@hisilicon.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
|
@ -27,25 +27,56 @@ static const struct simplefb_format formats[] = SIMPLEFB_FORMATS;
|
||||
__init bool sysfb_parse_mode(const struct screen_info *si,
|
||||
struct simplefb_platform_data *mode)
|
||||
{
|
||||
const struct simplefb_format *f;
|
||||
__u8 type;
|
||||
u32 bits_per_pixel;
|
||||
unsigned int i;
|
||||
|
||||
type = si->orig_video_isVGA;
|
||||
if (type != VIDEO_TYPE_VLFB && type != VIDEO_TYPE_EFI)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* The meaning of depth and bpp for direct-color formats is
|
||||
* inconsistent:
|
||||
*
|
||||
* - DRM format info specifies depth as the number of color
|
||||
* bits; including alpha, but not including filler bits.
|
||||
* - Linux' EFI platform code computes lfb_depth from the
|
||||
* individual color channels, including the reserved bits.
|
||||
* - VBE 1.1 defines lfb_depth for XRGB1555 as 16, but later
|
||||
* versions use 15.
|
||||
* - On the kernel command line, 'bpp' of 32 is usually
|
||||
* XRGB8888 including the filler bits, but 15 is XRGB1555
|
||||
* not including the filler bit.
|
||||
*
|
||||
* It's not easily possible to fix this in struct screen_info,
|
||||
* as this could break UAPI. The best solution is to compute
|
||||
* bits_per_pixel here and ignore lfb_depth. In the loop below,
|
||||
* ignore simplefb formats with alpha bits, as EFI and VESA
|
||||
* don't specify alpha channels.
|
||||
*/
|
||||
if (si->lfb_depth > 8) {
|
||||
bits_per_pixel = max(max3(si->red_size + si->red_pos,
|
||||
si->green_size + si->green_pos,
|
||||
si->blue_size + si->blue_pos),
|
||||
si->rsvd_size + si->rsvd_pos);
|
||||
} else {
|
||||
bits_per_pixel = si->lfb_depth;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(formats); ++i) {
|
||||
f = &formats[i];
|
||||
if (si->lfb_depth == f->bits_per_pixel &&
|
||||
const struct simplefb_format *f = &formats[i];
|
||||
|
||||
if (f->transp.length)
|
||||
continue; /* transparent formats are unsupported by VESA/EFI */
|
||||
|
||||
if (bits_per_pixel == f->bits_per_pixel &&
|
||||
si->red_size == f->red.length &&
|
||||
si->red_pos == f->red.offset &&
|
||||
si->green_size == f->green.length &&
|
||||
si->green_pos == f->green.offset &&
|
||||
si->blue_size == f->blue.length &&
|
||||
si->blue_pos == f->blue.offset &&
|
||||
si->rsvd_size == f->transp.length &&
|
||||
si->rsvd_pos == f->transp.offset) {
|
||||
si->blue_pos == f->blue.offset) {
|
||||
mode->format = f->name;
|
||||
mode->width = si->lfb_width;
|
||||
mode->height = si->lfb_height;
|
||||
|
@ -12,7 +12,6 @@ menuconfig DRM
|
||||
select HDMI
|
||||
select FB_CMDLINE
|
||||
select I2C
|
||||
select I2C_ALGOBIT
|
||||
select DMA_SHARED_BUFFER
|
||||
select SYNC_FILE
|
||||
# gallium uses SYS_kcmp for os_same_file_description() to de-duplicate
|
||||
|
@ -13,6 +13,8 @@ config DRM_AMDGPU
|
||||
select DRM_TTM_HELPER
|
||||
select POWER_SUPPLY
|
||||
select HWMON
|
||||
select I2C
|
||||
select I2C_ALGOBIT
|
||||
select BACKLIGHT_CLASS_DEVICE
|
||||
select INTERVAL_TREE
|
||||
select DRM_BUDDY
|
||||
|
@ -195,8 +195,8 @@ static int hdlcd_setup_mode_config(struct drm_device *drm)
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
static int hdlcd_show_underrun_count(struct seq_file *m, void *arg)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *)m->private;
|
||||
struct drm_device *drm = node->minor->dev;
|
||||
struct drm_debugfs_entry *entry = m->private;
|
||||
struct drm_device *drm = entry->dev;
|
||||
struct hdlcd_drm_private *hdlcd = drm_to_hdlcd_priv(drm);
|
||||
|
||||
seq_printf(m, "underrun : %d\n", atomic_read(&hdlcd->buffer_underrun_count));
|
||||
@ -208,8 +208,8 @@ static int hdlcd_show_underrun_count(struct seq_file *m, void *arg)
|
||||
|
||||
static int hdlcd_show_pxlclock(struct seq_file *m, void *arg)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *)m->private;
|
||||
struct drm_device *drm = node->minor->dev;
|
||||
struct drm_debugfs_entry *entry = m->private;
|
||||
struct drm_device *drm = entry->dev;
|
||||
struct hdlcd_drm_private *hdlcd = drm_to_hdlcd_priv(drm);
|
||||
unsigned long clkrate = clk_get_rate(hdlcd->clk);
|
||||
unsigned long mode_clock = hdlcd->crtc.mode.crtc_clock * 1000;
|
||||
@ -219,17 +219,10 @@ static int hdlcd_show_pxlclock(struct seq_file *m, void *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct drm_info_list hdlcd_debugfs_list[] = {
|
||||
static struct drm_debugfs_info hdlcd_debugfs_list[] = {
|
||||
{ "interrupt_count", hdlcd_show_underrun_count, 0 },
|
||||
{ "clocks", hdlcd_show_pxlclock, 0 },
|
||||
};
|
||||
|
||||
static void hdlcd_debugfs_init(struct drm_minor *minor)
|
||||
{
|
||||
drm_debugfs_create_files(hdlcd_debugfs_list,
|
||||
ARRAY_SIZE(hdlcd_debugfs_list),
|
||||
minor->debugfs_root, minor);
|
||||
}
|
||||
#endif
|
||||
|
||||
DEFINE_DRM_GEM_DMA_FOPS(fops);
|
||||
@ -237,9 +230,6 @@ DEFINE_DRM_GEM_DMA_FOPS(fops);
|
||||
static const struct drm_driver hdlcd_driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
|
||||
DRM_GEM_DMA_DRIVER_OPS,
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
.debugfs_init = hdlcd_debugfs_init,
|
||||
#endif
|
||||
.fops = &fops,
|
||||
.name = "hdlcd",
|
||||
.desc = "ARM HDLCD Controller DRM",
|
||||
@ -303,6 +293,10 @@ static int hdlcd_drm_bind(struct device *dev)
|
||||
drm_mode_config_reset(drm);
|
||||
drm_kms_helper_poll_init(drm);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
drm_debugfs_add_files(drm, hdlcd_debugfs_list, ARRAY_SIZE(hdlcd_debugfs_list));
|
||||
#endif
|
||||
|
||||
ret = drm_dev_register(drm, 0);
|
||||
if (ret)
|
||||
goto err_register;
|
||||
|
@ -4,6 +4,8 @@ config DRM_AST
|
||||
depends on DRM && PCI && MMU
|
||||
select DRM_GEM_SHMEM_HELPER
|
||||
select DRM_KMS_HELPER
|
||||
select I2C
|
||||
select I2C_ALGOBIT
|
||||
help
|
||||
Say yes for experimental AST GPU driver. Do not enable
|
||||
this driver without having a working -modesetting,
|
||||
|
@ -357,15 +357,16 @@ struct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev,
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
bridge = drm_panel_bridge_add_typed(panel, connector_type);
|
||||
if (!IS_ERR(bridge)) {
|
||||
*ptr = bridge;
|
||||
devres_add(dev, ptr);
|
||||
} else {
|
||||
if (IS_ERR(bridge)) {
|
||||
devres_free(ptr);
|
||||
return bridge;
|
||||
}
|
||||
|
||||
bridge->pre_enable_prev_first = panel->prepare_prev_first;
|
||||
|
||||
*ptr = bridge;
|
||||
devres_add(dev, ptr);
|
||||
|
||||
return bridge;
|
||||
}
|
||||
EXPORT_SYMBOL(devm_drm_panel_bridge_add_typed);
|
||||
|
@ -450,8 +450,8 @@ static int drm_atomic_helper_crtc_normalize_zpos(struct drm_crtc *crtc,
|
||||
int i, n = 0;
|
||||
int ret = 0;
|
||||
|
||||
DRM_DEBUG_ATOMIC("[CRTC:%d:%s] calculating normalized zpos values\n",
|
||||
crtc->base.id, crtc->name);
|
||||
drm_dbg_atomic(dev, "[CRTC:%d:%s] calculating normalized zpos values\n",
|
||||
crtc->base.id, crtc->name);
|
||||
|
||||
states = kmalloc_array(total_planes, sizeof(*states), GFP_KERNEL);
|
||||
if (!states)
|
||||
@ -469,9 +469,8 @@ static int drm_atomic_helper_crtc_normalize_zpos(struct drm_crtc *crtc,
|
||||
goto done;
|
||||
}
|
||||
states[n++] = plane_state;
|
||||
DRM_DEBUG_ATOMIC("[PLANE:%d:%s] processing zpos value %d\n",
|
||||
plane->base.id, plane->name,
|
||||
plane_state->zpos);
|
||||
drm_dbg_atomic(dev, "[PLANE:%d:%s] processing zpos value %d\n",
|
||||
plane->base.id, plane->name, plane_state->zpos);
|
||||
}
|
||||
|
||||
sort(states, n, sizeof(*states), drm_atomic_state_zpos_cmp, NULL);
|
||||
@ -480,8 +479,8 @@ static int drm_atomic_helper_crtc_normalize_zpos(struct drm_crtc *crtc,
|
||||
plane = states[i]->plane;
|
||||
|
||||
states[i]->normalized_zpos = i;
|
||||
DRM_DEBUG_ATOMIC("[PLANE:%d:%s] normalized zpos value %d\n",
|
||||
plane->base.id, plane->name, i);
|
||||
drm_dbg_atomic(dev, "[PLANE:%d:%s] normalized zpos value %d\n",
|
||||
plane->base.id, plane->name, i);
|
||||
}
|
||||
crtc_state->zpos_changed = true;
|
||||
|
||||
|
@ -128,14 +128,7 @@ static void drm_bridge_connector_hpd_cb(void *cb_data,
|
||||
drm_kms_helper_hotplug_event(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_bridge_connector_enable_hpd - Enable hot-plug detection for the connector
|
||||
* @connector: The DRM bridge connector
|
||||
*
|
||||
* This function enables hot-plug detection for the given bridge connector.
|
||||
* This is typically used by display drivers in their resume handler.
|
||||
*/
|
||||
void drm_bridge_connector_enable_hpd(struct drm_connector *connector)
|
||||
static void drm_bridge_connector_enable_hpd(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_bridge_connector *bridge_connector =
|
||||
to_drm_bridge_connector(connector);
|
||||
@ -145,17 +138,8 @@ void drm_bridge_connector_enable_hpd(struct drm_connector *connector)
|
||||
drm_bridge_hpd_enable(hpd, drm_bridge_connector_hpd_cb,
|
||||
bridge_connector);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_bridge_connector_enable_hpd);
|
||||
|
||||
/**
|
||||
* drm_bridge_connector_disable_hpd - Disable hot-plug detection for the
|
||||
* connector
|
||||
* @connector: The DRM bridge connector
|
||||
*
|
||||
* This function disables hot-plug detection for the given bridge connector.
|
||||
* This is typically used by display drivers in their suspend handler.
|
||||
*/
|
||||
void drm_bridge_connector_disable_hpd(struct drm_connector *connector)
|
||||
static void drm_bridge_connector_disable_hpd(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_bridge_connector *bridge_connector =
|
||||
to_drm_bridge_connector(connector);
|
||||
@ -164,7 +148,6 @@ void drm_bridge_connector_disable_hpd(struct drm_connector *connector)
|
||||
if (hpd)
|
||||
drm_bridge_hpd_disable(hpd);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_bridge_connector_disable_hpd);
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Bridge Connector Functions
|
||||
@ -305,6 +288,8 @@ static int drm_bridge_connector_get_modes(struct drm_connector *connector)
|
||||
static const struct drm_connector_helper_funcs drm_bridge_connector_helper_funcs = {
|
||||
.get_modes = drm_bridge_connector_get_modes,
|
||||
/* No need for .mode_valid(), the bridges are checked by the core. */
|
||||
.enable_hpd = drm_bridge_connector_enable_hpd,
|
||||
.disable_hpd = drm_bridge_connector_disable_hpd,
|
||||
};
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
@ -387,10 +372,8 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
|
||||
connector_type, ddc);
|
||||
drm_connector_helper_add(connector, &drm_bridge_connector_helper_funcs);
|
||||
|
||||
if (bridge_connector->bridge_hpd) {
|
||||
if (bridge_connector->bridge_hpd)
|
||||
connector->polled = DRM_CONNECTOR_POLL_HPD;
|
||||
drm_bridge_connector_enable_hpd(connector);
|
||||
}
|
||||
else if (bridge_connector->bridge_detect)
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT
|
||||
| DRM_CONNECTOR_POLL_DISCONNECT;
|
||||
|
@ -207,7 +207,7 @@ void drm_debugfs_create_files(const struct drm_info_list *files, int count,
|
||||
|
||||
tmp->minor = minor;
|
||||
tmp->dent = debugfs_create_file(files[i].name,
|
||||
S_IFREG | S_IRUGO, root, tmp,
|
||||
0444, root, tmp,
|
||||
&drm_debugfs_fops);
|
||||
tmp->info_ent = &files[i];
|
||||
|
||||
@ -246,7 +246,7 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id,
|
||||
dev->driver->debugfs_init(minor);
|
||||
|
||||
list_for_each_entry_safe(entry, tmp, &dev->debugfs_list, list) {
|
||||
debugfs_create_file(entry->file.name, S_IFREG | S_IRUGO,
|
||||
debugfs_create_file(entry->file.name, 0444,
|
||||
minor->debugfs_root, entry, &drm_debugfs_entry_fops);
|
||||
list_del(&entry->list);
|
||||
}
|
||||
@ -263,7 +263,7 @@ void drm_debugfs_late_register(struct drm_device *dev)
|
||||
return;
|
||||
|
||||
list_for_each_entry_safe(entry, tmp, &dev->debugfs_list, list) {
|
||||
debugfs_create_file(entry->file.name, S_IFREG | S_IRUGO,
|
||||
debugfs_create_file(entry->file.name, 0444,
|
||||
minor->debugfs_root, entry, &drm_debugfs_entry_fops);
|
||||
list_del(&entry->list);
|
||||
}
|
||||
@ -508,15 +508,15 @@ void drm_debugfs_connector_add(struct drm_connector *connector)
|
||||
connector->debugfs_entry = root;
|
||||
|
||||
/* force */
|
||||
debugfs_create_file("force", S_IRUGO | S_IWUSR, root, connector,
|
||||
debugfs_create_file("force", 0644, root, connector,
|
||||
&drm_connector_fops);
|
||||
|
||||
/* edid */
|
||||
debugfs_create_file("edid_override", S_IRUGO | S_IWUSR, root, connector,
|
||||
debugfs_create_file("edid_override", 0644, root, connector,
|
||||
&drm_edid_fops);
|
||||
|
||||
/* vrr range */
|
||||
debugfs_create_file("vrr_range", S_IRUGO, root, connector,
|
||||
debugfs_create_file("vrr_range", 0444, root, connector,
|
||||
&vrr_range_fops);
|
||||
|
||||
/* max bpc */
|
||||
|
@ -1726,117 +1726,132 @@ unlock:
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_pan_display);
|
||||
|
||||
/*
|
||||
* Allocates the backing storage and sets up the fbdev info structure through
|
||||
* the ->fb_probe callback.
|
||||
*/
|
||||
static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
|
||||
int preferred_bpp)
|
||||
static uint32_t drm_fb_helper_find_format(struct drm_fb_helper *fb_helper, const uint32_t *formats,
|
||||
size_t format_count, uint32_t bpp, uint32_t depth)
|
||||
{
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
uint32_t format;
|
||||
size_t i;
|
||||
|
||||
/*
|
||||
* Do not consider YUV or other complicated formats
|
||||
* for framebuffers. This means only legacy formats
|
||||
* are supported (fmt->depth is a legacy field), but
|
||||
* the framebuffer emulation can only deal with such
|
||||
* formats, specifically RGB/BGA formats.
|
||||
*/
|
||||
format = drm_mode_legacy_fb_format(bpp, depth);
|
||||
if (!format)
|
||||
goto err;
|
||||
|
||||
for (i = 0; i < format_count; ++i) {
|
||||
if (formats[i] == format)
|
||||
return format;
|
||||
}
|
||||
|
||||
err:
|
||||
/* We found nothing. */
|
||||
drm_warn(dev, "bpp/depth value of %u/%u not supported\n", bpp, depth);
|
||||
|
||||
return DRM_FORMAT_INVALID;
|
||||
}
|
||||
|
||||
static uint32_t drm_fb_helper_find_color_mode_format(struct drm_fb_helper *fb_helper,
|
||||
const uint32_t *formats, size_t format_count,
|
||||
unsigned int color_mode)
|
||||
{
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
uint32_t bpp, depth;
|
||||
|
||||
switch (color_mode) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 8:
|
||||
case 16:
|
||||
case 24:
|
||||
bpp = depth = color_mode;
|
||||
break;
|
||||
case 15:
|
||||
bpp = 16;
|
||||
depth = 15;
|
||||
break;
|
||||
case 32:
|
||||
bpp = 32;
|
||||
depth = 24;
|
||||
break;
|
||||
default:
|
||||
drm_info(dev, "unsupported color mode of %d\n", color_mode);
|
||||
return DRM_FORMAT_INVALID;
|
||||
}
|
||||
|
||||
return drm_fb_helper_find_format(fb_helper, formats, format_count, bpp, depth);
|
||||
}
|
||||
|
||||
static int __drm_fb_helper_find_sizes(struct drm_fb_helper *fb_helper, int preferred_bpp,
|
||||
struct drm_fb_helper_surface_size *sizes)
|
||||
{
|
||||
struct drm_client_dev *client = &fb_helper->client;
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
struct drm_mode_config *config = &dev->mode_config;
|
||||
int ret = 0;
|
||||
int crtc_count = 0;
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
struct drm_fb_helper_surface_size sizes;
|
||||
struct drm_connector *connector;
|
||||
struct drm_mode_set *mode_set;
|
||||
int best_depth = 0;
|
||||
uint32_t surface_format = DRM_FORMAT_INVALID;
|
||||
const struct drm_format_info *info;
|
||||
|
||||
memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size));
|
||||
sizes.surface_depth = 24;
|
||||
sizes.surface_bpp = 32;
|
||||
sizes.fb_width = (u32)-1;
|
||||
sizes.fb_height = (u32)-1;
|
||||
memset(sizes, 0, sizeof(*sizes));
|
||||
sizes->fb_width = (u32)-1;
|
||||
sizes->fb_height = (u32)-1;
|
||||
|
||||
/*
|
||||
* If driver picks 8 or 16 by default use that for both depth/bpp
|
||||
* to begin with
|
||||
*/
|
||||
if (preferred_bpp != sizes.surface_bpp)
|
||||
sizes.surface_depth = sizes.surface_bpp = preferred_bpp;
|
||||
|
||||
drm_connector_list_iter_begin(fb_helper->dev, &conn_iter);
|
||||
drm_client_for_each_connector_iter(connector, &conn_iter) {
|
||||
struct drm_cmdline_mode *cmdline_mode;
|
||||
|
||||
cmdline_mode = &connector->cmdline_mode;
|
||||
|
||||
if (cmdline_mode->bpp_specified) {
|
||||
switch (cmdline_mode->bpp) {
|
||||
case 8:
|
||||
sizes.surface_depth = sizes.surface_bpp = 8;
|
||||
break;
|
||||
case 15:
|
||||
sizes.surface_depth = 15;
|
||||
sizes.surface_bpp = 16;
|
||||
break;
|
||||
case 16:
|
||||
sizes.surface_depth = sizes.surface_bpp = 16;
|
||||
break;
|
||||
case 24:
|
||||
sizes.surface_depth = sizes.surface_bpp = 24;
|
||||
break;
|
||||
case 32:
|
||||
sizes.surface_depth = 24;
|
||||
sizes.surface_bpp = 32;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
|
||||
/*
|
||||
* If we run into a situation where, for example, the primary plane
|
||||
* supports RGBA5551 (16 bpp, depth 15) but not RGB565 (16 bpp, depth
|
||||
* 16) we need to scale down the depth of the sizes we request.
|
||||
*/
|
||||
mutex_lock(&client->modeset_mutex);
|
||||
drm_client_for_each_modeset(mode_set, client) {
|
||||
struct drm_crtc *crtc = mode_set->crtc;
|
||||
struct drm_plane *plane = crtc->primary;
|
||||
int j;
|
||||
|
||||
drm_dbg_kms(dev, "test CRTC %u primary plane\n", drm_crtc_index(crtc));
|
||||
|
||||
for (j = 0; j < plane->format_count; j++) {
|
||||
const struct drm_format_info *fmt;
|
||||
drm_connector_list_iter_begin(fb_helper->dev, &conn_iter);
|
||||
drm_client_for_each_connector_iter(connector, &conn_iter) {
|
||||
struct drm_cmdline_mode *cmdline_mode = &connector->cmdline_mode;
|
||||
|
||||
fmt = drm_format_info(plane->format_types[j]);
|
||||
|
||||
/*
|
||||
* Do not consider YUV or other complicated formats
|
||||
* for framebuffers. This means only legacy formats
|
||||
* are supported (fmt->depth is a legacy field) but
|
||||
* the framebuffer emulation can only deal with such
|
||||
* formats, specifically RGB/BGA formats.
|
||||
*/
|
||||
if (fmt->depth == 0)
|
||||
if (!cmdline_mode->bpp_specified)
|
||||
continue;
|
||||
|
||||
/* We found a perfect fit, great */
|
||||
if (fmt->depth == sizes.surface_depth) {
|
||||
best_depth = fmt->depth;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Skip depths above what we're looking for */
|
||||
if (fmt->depth > sizes.surface_depth)
|
||||
continue;
|
||||
|
||||
/* Best depth found so far */
|
||||
if (fmt->depth > best_depth)
|
||||
best_depth = fmt->depth;
|
||||
surface_format = drm_fb_helper_find_color_mode_format(fb_helper,
|
||||
plane->format_types,
|
||||
plane->format_count,
|
||||
cmdline_mode->bpp);
|
||||
if (surface_format != DRM_FORMAT_INVALID)
|
||||
break; /* found supported format */
|
||||
}
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
|
||||
if (surface_format != DRM_FORMAT_INVALID)
|
||||
break; /* found supported format */
|
||||
|
||||
/* try preferred color mode */
|
||||
surface_format = drm_fb_helper_find_color_mode_format(fb_helper,
|
||||
plane->format_types,
|
||||
plane->format_count,
|
||||
preferred_bpp);
|
||||
if (surface_format != DRM_FORMAT_INVALID)
|
||||
break; /* found supported format */
|
||||
}
|
||||
if (sizes.surface_depth != best_depth && best_depth) {
|
||||
drm_info(dev, "requested bpp %d, scaled depth down to %d",
|
||||
sizes.surface_bpp, best_depth);
|
||||
sizes.surface_depth = best_depth;
|
||||
|
||||
if (surface_format == DRM_FORMAT_INVALID) {
|
||||
/*
|
||||
* If none of the given color modes works, fall back
|
||||
* to XRGB8888. Drivers are expected to provide this
|
||||
* format for compatibility with legacy applications.
|
||||
*/
|
||||
drm_warn(dev, "No compatible format found\n");
|
||||
surface_format = drm_driver_legacy_fb_format(dev, 32, 24);
|
||||
}
|
||||
|
||||
info = drm_format_info(surface_format);
|
||||
sizes->surface_bpp = drm_format_info_bpp(info, 0);
|
||||
sizes->surface_depth = info->depth;
|
||||
|
||||
/* first up get a count of crtcs now in use and new min/maxes width/heights */
|
||||
crtc_count = 0;
|
||||
drm_client_for_each_modeset(mode_set, client) {
|
||||
@ -1858,8 +1873,10 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
|
||||
x = mode_set->x;
|
||||
y = mode_set->y;
|
||||
|
||||
sizes.surface_width = max_t(u32, desired_mode->hdisplay + x, sizes.surface_width);
|
||||
sizes.surface_height = max_t(u32, desired_mode->vdisplay + y, sizes.surface_height);
|
||||
sizes->surface_width =
|
||||
max_t(u32, desired_mode->hdisplay + x, sizes->surface_width);
|
||||
sizes->surface_height =
|
||||
max_t(u32, desired_mode->vdisplay + y, sizes->surface_height);
|
||||
|
||||
for (j = 0; j < mode_set->num_connectors; j++) {
|
||||
struct drm_connector *connector = mode_set->connectors[j];
|
||||
@ -1875,28 +1892,63 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
|
||||
}
|
||||
|
||||
if (lasth)
|
||||
sizes.fb_width = min_t(u32, desired_mode->hdisplay + x, sizes.fb_width);
|
||||
sizes->fb_width = min_t(u32, desired_mode->hdisplay + x, sizes->fb_width);
|
||||
if (lastv)
|
||||
sizes.fb_height = min_t(u32, desired_mode->vdisplay + y, sizes.fb_height);
|
||||
sizes->fb_height = min_t(u32, desired_mode->vdisplay + y, sizes->fb_height);
|
||||
}
|
||||
mutex_unlock(&client->modeset_mutex);
|
||||
|
||||
if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) {
|
||||
if (crtc_count == 0 || sizes->fb_width == -1 || sizes->fb_height == -1) {
|
||||
drm_info(dev, "Cannot find any crtc or sizes\n");
|
||||
|
||||
/* First time: disable all crtc's.. */
|
||||
if (!fb_helper->deferred_setup)
|
||||
drm_client_modeset_commit(client);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_fb_helper_find_sizes(struct drm_fb_helper *fb_helper, int preferred_bpp,
|
||||
struct drm_fb_helper_surface_size *sizes)
|
||||
{
|
||||
struct drm_client_dev *client = &fb_helper->client;
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
struct drm_mode_config *config = &dev->mode_config;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&client->modeset_mutex);
|
||||
ret = __drm_fb_helper_find_sizes(fb_helper, preferred_bpp, sizes);
|
||||
mutex_unlock(&client->modeset_mutex);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Handle our overallocation */
|
||||
sizes.surface_height *= drm_fbdev_overalloc;
|
||||
sizes.surface_height /= 100;
|
||||
if (sizes.surface_height > config->max_height) {
|
||||
sizes->surface_height *= drm_fbdev_overalloc;
|
||||
sizes->surface_height /= 100;
|
||||
if (sizes->surface_height > config->max_height) {
|
||||
drm_dbg_kms(dev, "Fbdev over-allocation too large; clamping height to %d\n",
|
||||
config->max_height);
|
||||
sizes.surface_height = config->max_height;
|
||||
sizes->surface_height = config->max_height;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocates the backing storage and sets up the fbdev info structure through
|
||||
* the ->fb_probe callback.
|
||||
*/
|
||||
static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
|
||||
int preferred_bpp)
|
||||
{
|
||||
struct drm_client_dev *client = &fb_helper->client;
|
||||
struct drm_fb_helper_surface_size sizes;
|
||||
int ret;
|
||||
|
||||
ret = drm_fb_helper_find_sizes(fb_helper, preferred_bpp, &sizes);
|
||||
if (ret) {
|
||||
/* First time: disable all crtc's.. */
|
||||
if (!fb_helper->deferred_setup)
|
||||
drm_client_modeset_commit(client);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
|
||||
|
@ -245,10 +245,10 @@ void drm_file_free(struct drm_file *file)
|
||||
|
||||
dev = file->minor->dev;
|
||||
|
||||
DRM_DEBUG("comm=\"%s\", pid=%d, dev=0x%lx, open_count=%d\n",
|
||||
current->comm, task_pid_nr(current),
|
||||
(long)old_encode_dev(file->minor->kdev->devt),
|
||||
atomic_read(&dev->open_count));
|
||||
drm_dbg_core(dev, "comm=\"%s\", pid=%d, dev=0x%lx, open_count=%d\n",
|
||||
current->comm, task_pid_nr(current),
|
||||
(long)old_encode_dev(file->minor->kdev->devt),
|
||||
atomic_read(&dev->open_count));
|
||||
|
||||
#ifdef CONFIG_DRM_LEGACY
|
||||
if (drm_core_check_feature(dev, DRIVER_LEGACY) &&
|
||||
@ -340,8 +340,8 @@ int drm_open_helper(struct file *filp, struct drm_minor *minor)
|
||||
dev->switch_power_state != DRM_SWITCH_POWER_DYNAMIC_OFF)
|
||||
return -EINVAL;
|
||||
|
||||
DRM_DEBUG("comm=\"%s\", pid=%d, minor=%d\n", current->comm,
|
||||
task_pid_nr(current), minor->index);
|
||||
drm_dbg_core(dev, "comm=\"%s\", pid=%d, minor=%d\n",
|
||||
current->comm, task_pid_nr(current), minor->index);
|
||||
|
||||
priv = drm_file_alloc(minor);
|
||||
if (IS_ERR(priv))
|
||||
@ -450,11 +450,11 @@ EXPORT_SYMBOL(drm_open);
|
||||
|
||||
void drm_lastclose(struct drm_device * dev)
|
||||
{
|
||||
DRM_DEBUG("\n");
|
||||
drm_dbg_core(dev, "\n");
|
||||
|
||||
if (dev->driver->lastclose)
|
||||
dev->driver->lastclose(dev);
|
||||
DRM_DEBUG("driver lastclose completed\n");
|
||||
drm_dbg_core(dev, "driver lastclose completed\n");
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_LEGACY))
|
||||
drm_legacy_dev_reinit(dev);
|
||||
@ -485,7 +485,7 @@ int drm_release(struct inode *inode, struct file *filp)
|
||||
if (drm_dev_needs_global_mutex(dev))
|
||||
mutex_lock(&drm_global_mutex);
|
||||
|
||||
DRM_DEBUG("open_count = %d\n", atomic_read(&dev->open_count));
|
||||
drm_dbg_core(dev, "open_count = %d\n", atomic_read(&dev->open_count));
|
||||
|
||||
drm_close_helper(filp);
|
||||
|
||||
|
@ -322,7 +322,7 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb332);
|
||||
|
||||
static void drm_fb_xrgb8888_to_rgb565_line(void *dbuf, const void *sbuf, unsigned int pixels)
|
||||
{
|
||||
u16 *dbuf16 = dbuf;
|
||||
__le16 *dbuf16 = dbuf;
|
||||
const __le32 *sbuf32 = sbuf;
|
||||
unsigned int x;
|
||||
u16 val16;
|
||||
@ -333,14 +333,15 @@ static void drm_fb_xrgb8888_to_rgb565_line(void *dbuf, const void *sbuf, unsigne
|
||||
val16 = ((pix & 0x00F80000) >> 8) |
|
||||
((pix & 0x0000FC00) >> 5) |
|
||||
((pix & 0x000000F8) >> 3);
|
||||
dbuf16[x] = val16;
|
||||
dbuf16[x] = cpu_to_le16(val16);
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: implement this helper as conversion to RGB565|BIG_ENDIAN */
|
||||
static void drm_fb_xrgb8888_to_rgb565_swab_line(void *dbuf, const void *sbuf,
|
||||
unsigned int pixels)
|
||||
{
|
||||
u16 *dbuf16 = dbuf;
|
||||
__le16 *dbuf16 = dbuf;
|
||||
const __le32 *sbuf32 = sbuf;
|
||||
unsigned int x;
|
||||
u16 val16;
|
||||
@ -351,7 +352,7 @@ static void drm_fb_xrgb8888_to_rgb565_swab_line(void *dbuf, const void *sbuf,
|
||||
val16 = ((pix & 0x00F80000) >> 8) |
|
||||
((pix & 0x0000FC00) >> 5) |
|
||||
((pix & 0x000000F8) >> 3);
|
||||
dbuf16[x] = swab16(val16);
|
||||
dbuf16[x] = cpu_to_le16(swab16(val16));
|
||||
}
|
||||
}
|
||||
|
||||
@ -395,6 +396,161 @@ void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pi
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565);
|
||||
|
||||
static void drm_fb_xrgb8888_to_xrgb1555_line(void *dbuf, const void *sbuf, unsigned int pixels)
|
||||
{
|
||||
__le16 *dbuf16 = dbuf;
|
||||
const __le32 *sbuf32 = sbuf;
|
||||
unsigned int x;
|
||||
u16 val16;
|
||||
u32 pix;
|
||||
|
||||
for (x = 0; x < pixels; x++) {
|
||||
pix = le32_to_cpu(sbuf32[x]);
|
||||
val16 = ((pix & 0x00f80000) >> 9) |
|
||||
((pix & 0x0000f800) >> 6) |
|
||||
((pix & 0x000000f8) >> 3);
|
||||
dbuf16[x] = cpu_to_le16(val16);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_fb_xrgb8888_to_xrgb1555 - Convert XRGB8888 to XRGB1555 clip buffer
|
||||
* @dst: Array of XRGB1555 destination buffers
|
||||
* @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
|
||||
* within @dst; can be NULL if scanlines are stored next to each other.
|
||||
* @src: Array of XRGB8888 source buffer
|
||||
* @fb: DRM framebuffer
|
||||
* @clip: Clip rectangle area to copy
|
||||
*
|
||||
* This function copies parts of a framebuffer to display memory and converts
|
||||
* the color format during the process. The parameters @dst, @dst_pitch and
|
||||
* @src refer to arrays. Each array must have at least as many entries as
|
||||
* there are planes in @fb's format. Each entry stores the value for the
|
||||
* format's respective color plane at the same index.
|
||||
*
|
||||
* This function does not apply clipping on @dst (i.e. the destination is at the
|
||||
* top-left corner).
|
||||
*
|
||||
* Drivers can use this function for XRGB1555 devices that don't support
|
||||
* XRGB8888 natively.
|
||||
*/
|
||||
void drm_fb_xrgb8888_to_xrgb1555(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip)
|
||||
{
|
||||
static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
|
||||
2,
|
||||
};
|
||||
|
||||
drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
|
||||
drm_fb_xrgb8888_to_xrgb1555_line);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb1555);
|
||||
|
||||
static void drm_fb_xrgb8888_to_argb1555_line(void *dbuf, const void *sbuf, unsigned int pixels)
|
||||
{
|
||||
__le16 *dbuf16 = dbuf;
|
||||
const __le32 *sbuf32 = sbuf;
|
||||
unsigned int x;
|
||||
u16 val16;
|
||||
u32 pix;
|
||||
|
||||
for (x = 0; x < pixels; x++) {
|
||||
pix = le32_to_cpu(sbuf32[x]);
|
||||
val16 = BIT(15) | /* set alpha bit */
|
||||
((pix & 0x00f80000) >> 9) |
|
||||
((pix & 0x0000f800) >> 6) |
|
||||
((pix & 0x000000f8) >> 3);
|
||||
dbuf16[x] = cpu_to_le16(val16);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_fb_xrgb8888_to_argb1555 - Convert XRGB8888 to ARGB1555 clip buffer
|
||||
* @dst: Array of ARGB1555 destination buffers
|
||||
* @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
|
||||
* within @dst; can be NULL if scanlines are stored next to each other.
|
||||
* @src: Array of XRGB8888 source buffer
|
||||
* @fb: DRM framebuffer
|
||||
* @clip: Clip rectangle area to copy
|
||||
*
|
||||
* This function copies parts of a framebuffer to display memory and converts
|
||||
* the color format during the process. The parameters @dst, @dst_pitch and
|
||||
* @src refer to arrays. Each array must have at least as many entries as
|
||||
* there are planes in @fb's format. Each entry stores the value for the
|
||||
* format's respective color plane at the same index.
|
||||
*
|
||||
* This function does not apply clipping on @dst (i.e. the destination is at the
|
||||
* top-left corner).
|
||||
*
|
||||
* Drivers can use this function for ARGB1555 devices that don't support
|
||||
* XRGB8888 natively. It sets an opaque alpha channel as part of the conversion.
|
||||
*/
|
||||
void drm_fb_xrgb8888_to_argb1555(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip)
|
||||
{
|
||||
static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
|
||||
2,
|
||||
};
|
||||
|
||||
drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
|
||||
drm_fb_xrgb8888_to_argb1555_line);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb1555);
|
||||
|
||||
static void drm_fb_xrgb8888_to_rgba5551_line(void *dbuf, const void *sbuf, unsigned int pixels)
|
||||
{
|
||||
__le16 *dbuf16 = dbuf;
|
||||
const __le32 *sbuf32 = sbuf;
|
||||
unsigned int x;
|
||||
u16 val16;
|
||||
u32 pix;
|
||||
|
||||
for (x = 0; x < pixels; x++) {
|
||||
pix = le32_to_cpu(sbuf32[x]);
|
||||
val16 = ((pix & 0x00f80000) >> 8) |
|
||||
((pix & 0x0000f800) >> 5) |
|
||||
((pix & 0x000000f8) >> 2) |
|
||||
BIT(0); /* set alpha bit */
|
||||
dbuf16[x] = cpu_to_le16(val16);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_fb_xrgb8888_to_rgba5551 - Convert XRGB8888 to RGBA5551 clip buffer
|
||||
* @dst: Array of RGBA5551 destination buffers
|
||||
* @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
|
||||
* within @dst; can be NULL if scanlines are stored next to each other.
|
||||
* @src: Array of XRGB8888 source buffer
|
||||
* @fb: DRM framebuffer
|
||||
* @clip: Clip rectangle area to copy
|
||||
*
|
||||
* This function copies parts of a framebuffer to display memory and converts
|
||||
* the color format during the process. The parameters @dst, @dst_pitch and
|
||||
* @src refer to arrays. Each array must have at least as many entries as
|
||||
* there are planes in @fb's format. Each entry stores the value for the
|
||||
* format's respective color plane at the same index.
|
||||
*
|
||||
* This function does not apply clipping on @dst (i.e. the destination is at the
|
||||
* top-left corner).
|
||||
*
|
||||
* Drivers can use this function for RGBA5551 devices that don't support
|
||||
* XRGB8888 natively. It sets an opaque alpha channel as part of the conversion.
|
||||
*/
|
||||
void drm_fb_xrgb8888_to_rgba5551(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip)
|
||||
{
|
||||
static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
|
||||
2,
|
||||
};
|
||||
|
||||
drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
|
||||
drm_fb_xrgb8888_to_rgba5551_line);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgba5551);
|
||||
|
||||
static void drm_fb_xrgb8888_to_rgb888_line(void *dbuf, const void *sbuf, unsigned int pixels)
|
||||
{
|
||||
u8 *dbuf8 = dbuf;
|
||||
@ -404,6 +560,7 @@ static void drm_fb_xrgb8888_to_rgb888_line(void *dbuf, const void *sbuf, unsigne
|
||||
|
||||
for (x = 0; x < pixels; x++) {
|
||||
pix = le32_to_cpu(sbuf32[x]);
|
||||
/* write blue-green-red to output in little endianness */
|
||||
*dbuf8++ = (pix & 0x000000FF) >> 0;
|
||||
*dbuf8++ = (pix & 0x0000FF00) >> 8;
|
||||
*dbuf8++ = (pix & 0x00FF0000) >> 16;
|
||||
@ -444,64 +601,53 @@ void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pi
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888);
|
||||
|
||||
static void drm_fb_rgb565_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigned int pixels)
|
||||
static void drm_fb_xrgb8888_to_argb8888_line(void *dbuf, const void *sbuf, unsigned int pixels)
|
||||
{
|
||||
__le32 *dbuf32 = dbuf;
|
||||
const __le16 *sbuf16 = sbuf;
|
||||
const __le32 *sbuf32 = sbuf;
|
||||
unsigned int x;
|
||||
u32 pix;
|
||||
|
||||
for (x = 0; x < pixels; x++) {
|
||||
u16 val16 = le16_to_cpu(sbuf16[x]);
|
||||
u32 val32 = ((val16 & 0xf800) << 8) |
|
||||
((val16 & 0x07e0) << 5) |
|
||||
((val16 & 0x001f) << 3);
|
||||
val32 = 0xff000000 | val32 |
|
||||
((val32 >> 3) & 0x00070007) |
|
||||
((val32 >> 2) & 0x00000300);
|
||||
dbuf32[x] = cpu_to_le32(val32);
|
||||
}
|
||||
}
|
||||
|
||||
static void drm_fb_rgb565_to_xrgb8888(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src,
|
||||
const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip)
|
||||
{
|
||||
static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
|
||||
4,
|
||||
};
|
||||
|
||||
drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
|
||||
drm_fb_rgb565_to_xrgb8888_line);
|
||||
}
|
||||
|
||||
static void drm_fb_rgb888_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigned int pixels)
|
||||
{
|
||||
__le32 *dbuf32 = dbuf;
|
||||
const u8 *sbuf8 = sbuf;
|
||||
unsigned int x;
|
||||
|
||||
for (x = 0; x < pixels; x++) {
|
||||
u8 r = *sbuf8++;
|
||||
u8 g = *sbuf8++;
|
||||
u8 b = *sbuf8++;
|
||||
u32 pix = 0xff000000 | (r << 16) | (g << 8) | b;
|
||||
pix = le32_to_cpu(sbuf32[x]);
|
||||
pix |= GENMASK(31, 24); /* fill alpha bits */
|
||||
dbuf32[x] = cpu_to_le32(pix);
|
||||
}
|
||||
}
|
||||
|
||||
static void drm_fb_rgb888_to_xrgb8888(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src,
|
||||
const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip)
|
||||
/**
|
||||
* drm_fb_xrgb8888_to_argb8888 - Convert XRGB8888 to ARGB8888 clip buffer
|
||||
* @dst: Array of ARGB8888 destination buffers
|
||||
* @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
|
||||
* within @dst; can be NULL if scanlines are stored next to each other.
|
||||
* @src: Array of XRGB8888 source buffer
|
||||
* @fb: DRM framebuffer
|
||||
* @clip: Clip rectangle area to copy
|
||||
*
|
||||
* This function copies parts of a framebuffer to display memory and converts the
|
||||
* color format during the process. The parameters @dst, @dst_pitch and @src refer
|
||||
* to arrays. Each array must have at least as many entries as there are planes in
|
||||
* @fb's format. Each entry stores the value for the format's respective color plane
|
||||
* at the same index.
|
||||
*
|
||||
* This function does not apply clipping on @dst (i.e. the destination is at the
|
||||
* top-left corner).
|
||||
*
|
||||
* Drivers can use this function for ARGB8888 devices that don't support XRGB8888
|
||||
* natively. It sets an opaque alpha channel as part of the conversion.
|
||||
*/
|
||||
void drm_fb_xrgb8888_to_argb8888(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip)
|
||||
{
|
||||
static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
|
||||
4,
|
||||
};
|
||||
|
||||
drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
|
||||
drm_fb_rgb888_to_xrgb8888_line);
|
||||
drm_fb_xrgb8888_to_argb8888_line);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb8888);
|
||||
|
||||
static void drm_fb_xrgb8888_to_xrgb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels)
|
||||
{
|
||||
@ -555,6 +701,59 @@ void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *d
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb2101010);
|
||||
|
||||
static void drm_fb_xrgb8888_to_argb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels)
|
||||
{
|
||||
__le32 *dbuf32 = dbuf;
|
||||
const __le32 *sbuf32 = sbuf;
|
||||
unsigned int x;
|
||||
u32 val32;
|
||||
u32 pix;
|
||||
|
||||
for (x = 0; x < pixels; x++) {
|
||||
pix = le32_to_cpu(sbuf32[x]);
|
||||
val32 = ((pix & 0x000000ff) << 2) |
|
||||
((pix & 0x0000ff00) << 4) |
|
||||
((pix & 0x00ff0000) << 6);
|
||||
pix = GENMASK(31, 30) | /* set alpha bits */
|
||||
val32 | ((val32 >> 8) & 0x00300c03);
|
||||
*dbuf32++ = cpu_to_le32(pix);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_fb_xrgb8888_to_argb2101010 - Convert XRGB8888 to ARGB2101010 clip buffer
|
||||
* @dst: Array of ARGB2101010 destination buffers
|
||||
* @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
|
||||
* within @dst; can be NULL if scanlines are stored next to each other.
|
||||
* @src: Array of XRGB8888 source buffers
|
||||
* @fb: DRM framebuffer
|
||||
* @clip: Clip rectangle area to copy
|
||||
*
|
||||
* This function copies parts of a framebuffer to display memory and converts
|
||||
* the color format during the process. The parameters @dst, @dst_pitch and
|
||||
* @src refer to arrays. Each array must have at least as many entries as
|
||||
* there are planes in @fb's format. Each entry stores the value for the
|
||||
* format's respective color plane at the same index.
|
||||
*
|
||||
* This function does not apply clipping on @dst (i.e. the destination is at the
|
||||
* top-left corner).
|
||||
*
|
||||
* Drivers can use this function for ARGB2101010 devices that don't support XRGB8888
|
||||
* natively.
|
||||
*/
|
||||
void drm_fb_xrgb8888_to_argb2101010(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip)
|
||||
{
|
||||
static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
|
||||
4,
|
||||
};
|
||||
|
||||
drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
|
||||
drm_fb_xrgb8888_to_argb2101010_line);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb2101010);
|
||||
|
||||
static void drm_fb_xrgb8888_to_gray8_line(void *dbuf, const void *sbuf, unsigned int pixels)
|
||||
{
|
||||
u8 *dbuf8 = dbuf;
|
||||
@ -641,50 +840,41 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d
|
||||
{
|
||||
uint32_t fb_format = fb->format->format;
|
||||
|
||||
/* treat alpha channel like filler bits */
|
||||
if (fb_format == DRM_FORMAT_ARGB8888)
|
||||
fb_format = DRM_FORMAT_XRGB8888;
|
||||
if (dst_format == DRM_FORMAT_ARGB8888)
|
||||
dst_format = DRM_FORMAT_XRGB8888;
|
||||
if (fb_format == DRM_FORMAT_ARGB2101010)
|
||||
fb_format = DRM_FORMAT_XRGB2101010;
|
||||
if (dst_format == DRM_FORMAT_ARGB2101010)
|
||||
dst_format = DRM_FORMAT_XRGB2101010;
|
||||
|
||||
if (dst_format == fb_format) {
|
||||
if (fb_format == dst_format) {
|
||||
drm_fb_memcpy(dst, dst_pitch, src, fb, clip);
|
||||
return 0;
|
||||
|
||||
} else if (dst_format == DRM_FORMAT_RGB565) {
|
||||
if (fb_format == DRM_FORMAT_XRGB8888) {
|
||||
} else if (fb_format == (dst_format | DRM_FORMAT_BIG_ENDIAN)) {
|
||||
drm_fb_swab(dst, dst_pitch, src, fb, clip, false);
|
||||
return 0;
|
||||
} else if (fb_format == (dst_format & ~DRM_FORMAT_BIG_ENDIAN)) {
|
||||
drm_fb_swab(dst, dst_pitch, src, fb, clip, false);
|
||||
return 0;
|
||||
} else if (fb_format == DRM_FORMAT_XRGB8888) {
|
||||
if (dst_format == DRM_FORMAT_RGB565) {
|
||||
drm_fb_xrgb8888_to_rgb565(dst, dst_pitch, src, fb, clip, false);
|
||||
return 0;
|
||||
}
|
||||
} else if (dst_format == (DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN)) {
|
||||
if (fb_format == DRM_FORMAT_RGB565) {
|
||||
drm_fb_swab(dst, dst_pitch, src, fb, clip, false);
|
||||
} else if (dst_format == DRM_FORMAT_XRGB1555) {
|
||||
drm_fb_xrgb8888_to_xrgb1555(dst, dst_pitch, src, fb, clip);
|
||||
return 0;
|
||||
}
|
||||
} else if (dst_format == DRM_FORMAT_RGB888) {
|
||||
if (fb_format == DRM_FORMAT_XRGB8888) {
|
||||
} else if (dst_format == DRM_FORMAT_ARGB1555) {
|
||||
drm_fb_xrgb8888_to_argb1555(dst, dst_pitch, src, fb, clip);
|
||||
return 0;
|
||||
} else if (dst_format == DRM_FORMAT_RGBA5551) {
|
||||
drm_fb_xrgb8888_to_rgba5551(dst, dst_pitch, src, fb, clip);
|
||||
return 0;
|
||||
} else if (dst_format == DRM_FORMAT_RGB888) {
|
||||
drm_fb_xrgb8888_to_rgb888(dst, dst_pitch, src, fb, clip);
|
||||
return 0;
|
||||
}
|
||||
} else if (dst_format == DRM_FORMAT_XRGB8888) {
|
||||
if (fb_format == DRM_FORMAT_RGB888) {
|
||||
drm_fb_rgb888_to_xrgb8888(dst, dst_pitch, src, fb, clip);
|
||||
} else if (dst_format == DRM_FORMAT_ARGB8888) {
|
||||
drm_fb_xrgb8888_to_argb8888(dst, dst_pitch, src, fb, clip);
|
||||
return 0;
|
||||
} else if (fb_format == DRM_FORMAT_RGB565) {
|
||||
drm_fb_rgb565_to_xrgb8888(dst, dst_pitch, src, fb, clip);
|
||||
return 0;
|
||||
}
|
||||
} else if (dst_format == DRM_FORMAT_XRGB2101010) {
|
||||
if (fb_format == DRM_FORMAT_XRGB8888) {
|
||||
} else if (dst_format == DRM_FORMAT_XRGB2101010) {
|
||||
drm_fb_xrgb8888_to_xrgb2101010(dst, dst_pitch, src, fb, clip);
|
||||
return 0;
|
||||
}
|
||||
} else if (dst_format == DRM_FORMAT_BGRX8888) {
|
||||
if (fb_format == DRM_FORMAT_XRGB8888) {
|
||||
} else if (dst_format == DRM_FORMAT_ARGB2101010) {
|
||||
drm_fb_xrgb8888_to_argb2101010(dst, dst_pitch, src, fb, clip);
|
||||
return 0;
|
||||
} else if (dst_format == DRM_FORMAT_BGRX8888) {
|
||||
drm_fb_swab(dst, dst_pitch, src, fb, clip, false);
|
||||
return 0;
|
||||
}
|
||||
@ -805,6 +995,39 @@ void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitc
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_xrgb8888_to_mono);
|
||||
|
||||
static uint32_t drm_fb_nonalpha_fourcc(uint32_t fourcc)
|
||||
{
|
||||
/* only handle formats with depth != 0 and alpha channel */
|
||||
switch (fourcc) {
|
||||
case DRM_FORMAT_ARGB1555:
|
||||
return DRM_FORMAT_XRGB1555;
|
||||
case DRM_FORMAT_ABGR1555:
|
||||
return DRM_FORMAT_XBGR1555;
|
||||
case DRM_FORMAT_RGBA5551:
|
||||
return DRM_FORMAT_RGBX5551;
|
||||
case DRM_FORMAT_BGRA5551:
|
||||
return DRM_FORMAT_BGRX5551;
|
||||
case DRM_FORMAT_ARGB8888:
|
||||
return DRM_FORMAT_XRGB8888;
|
||||
case DRM_FORMAT_ABGR8888:
|
||||
return DRM_FORMAT_XBGR8888;
|
||||
case DRM_FORMAT_RGBA8888:
|
||||
return DRM_FORMAT_RGBX8888;
|
||||
case DRM_FORMAT_BGRA8888:
|
||||
return DRM_FORMAT_BGRX8888;
|
||||
case DRM_FORMAT_ARGB2101010:
|
||||
return DRM_FORMAT_XRGB2101010;
|
||||
case DRM_FORMAT_ABGR2101010:
|
||||
return DRM_FORMAT_XBGR2101010;
|
||||
case DRM_FORMAT_RGBA1010102:
|
||||
return DRM_FORMAT_RGBX1010102;
|
||||
case DRM_FORMAT_BGRA1010102:
|
||||
return DRM_FORMAT_BGRX1010102;
|
||||
}
|
||||
|
||||
return fourcc;
|
||||
}
|
||||
|
||||
static bool is_listed_fourcc(const uint32_t *fourccs, size_t nfourccs, uint32_t fourcc)
|
||||
{
|
||||
const uint32_t *fourccs_end = fourccs + nfourccs;
|
||||
@ -817,73 +1040,48 @@ static bool is_listed_fourcc(const uint32_t *fourccs, size_t nfourccs, uint32_t
|
||||
return false;
|
||||
}
|
||||
|
||||
static const uint32_t conv_from_xrgb8888[] = {
|
||||
DRM_FORMAT_XRGB8888,
|
||||
DRM_FORMAT_ARGB8888,
|
||||
DRM_FORMAT_XRGB2101010,
|
||||
DRM_FORMAT_ARGB2101010,
|
||||
DRM_FORMAT_RGB565,
|
||||
DRM_FORMAT_RGB888,
|
||||
};
|
||||
|
||||
static const uint32_t conv_from_rgb565_888[] = {
|
||||
DRM_FORMAT_XRGB8888,
|
||||
DRM_FORMAT_ARGB8888,
|
||||
};
|
||||
|
||||
static bool is_conversion_supported(uint32_t from, uint32_t to)
|
||||
{
|
||||
switch (from) {
|
||||
case DRM_FORMAT_XRGB8888:
|
||||
case DRM_FORMAT_ARGB8888:
|
||||
return is_listed_fourcc(conv_from_xrgb8888, ARRAY_SIZE(conv_from_xrgb8888), to);
|
||||
case DRM_FORMAT_RGB565:
|
||||
case DRM_FORMAT_RGB888:
|
||||
return is_listed_fourcc(conv_from_rgb565_888, ARRAY_SIZE(conv_from_rgb565_888), to);
|
||||
case DRM_FORMAT_XRGB2101010:
|
||||
return to == DRM_FORMAT_ARGB2101010;
|
||||
case DRM_FORMAT_ARGB2101010:
|
||||
return to == DRM_FORMAT_XRGB2101010;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_fb_build_fourcc_list - Filters a list of supported color formats against
|
||||
* the device's native formats
|
||||
* @dev: DRM device
|
||||
* @native_fourccs: 4CC codes of natively supported color formats
|
||||
* @native_nfourccs: The number of entries in @native_fourccs
|
||||
* @driver_fourccs: 4CC codes of all driver-supported color formats
|
||||
* @driver_nfourccs: The number of entries in @driver_fourccs
|
||||
* @fourccs_out: Returns 4CC codes of supported color formats
|
||||
* @nfourccs_out: The number of available entries in @fourccs_out
|
||||
*
|
||||
* This function create a list of supported color format from natively
|
||||
* supported formats and the emulated formats.
|
||||
* supported formats and additional emulated formats.
|
||||
* At a minimum, most userspace programs expect at least support for
|
||||
* XRGB8888 on the primary plane. Devices that have to emulate the
|
||||
* format, and possibly others, can use drm_fb_build_fourcc_list() to
|
||||
* create a list of supported color formats. The returned list can
|
||||
* be handed over to drm_universal_plane_init() et al. Native formats
|
||||
* will go before emulated formats. Other heuristics might be applied
|
||||
* will go before emulated formats. Native formats with alpha channel
|
||||
* will be replaced by such without, as primary planes usually don't
|
||||
* support alpha. Other heuristics might be applied
|
||||
* to optimize the order. Formats near the beginning of the list are
|
||||
* usually preferred over formats near the end of the list. Formats
|
||||
* without conversion helpers will be skipped. New drivers should only
|
||||
* pass in XRGB8888 and avoid exposing additional emulated formats.
|
||||
* usually preferred over formats near the end of the list.
|
||||
*
|
||||
* Returns:
|
||||
* The number of color-formats 4CC codes returned in @fourccs_out.
|
||||
*/
|
||||
size_t drm_fb_build_fourcc_list(struct drm_device *dev,
|
||||
const u32 *native_fourccs, size_t native_nfourccs,
|
||||
const u32 *driver_fourccs, size_t driver_nfourccs,
|
||||
u32 *fourccs_out, size_t nfourccs_out)
|
||||
{
|
||||
/*
|
||||
* XRGB8888 is the default fallback format for most of userspace
|
||||
* and it's currently the only format that should be emulated for
|
||||
* the primary plane. Only if there's ever another default fallback,
|
||||
* it should be added here.
|
||||
*/
|
||||
static const uint32_t extra_fourccs[] = {
|
||||
DRM_FORMAT_XRGB8888,
|
||||
};
|
||||
static const size_t extra_nfourccs = ARRAY_SIZE(extra_fourccs);
|
||||
|
||||
u32 *fourccs = fourccs_out;
|
||||
const u32 *fourccs_end = fourccs_out + nfourccs_out;
|
||||
uint32_t native_format = 0;
|
||||
size_t i;
|
||||
|
||||
/*
|
||||
@ -891,7 +1089,12 @@ size_t drm_fb_build_fourcc_list(struct drm_device *dev,
|
||||
*/
|
||||
|
||||
for (i = 0; i < native_nfourccs; ++i) {
|
||||
u32 fourcc = native_fourccs[i];
|
||||
/*
|
||||
* Several DTs, boot loaders and firmware report native
|
||||
* alpha formats that are non-alpha formats instead. So
|
||||
* replace alpha formats by non-alpha formats.
|
||||
*/
|
||||
u32 fourcc = drm_fb_nonalpha_fourcc(native_fourccs[i]);
|
||||
|
||||
if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) {
|
||||
continue; /* skip duplicate entries */
|
||||
@ -902,14 +1105,6 @@ size_t drm_fb_build_fourcc_list(struct drm_device *dev,
|
||||
|
||||
drm_dbg_kms(dev, "adding native format %p4cc\n", &fourcc);
|
||||
|
||||
/*
|
||||
* There should only be one native format with the current API.
|
||||
* This API needs to be refactored to correctly support arbitrary
|
||||
* sets of native formats, since it needs to report which native
|
||||
* format to use for each emulated format.
|
||||
*/
|
||||
if (!native_format)
|
||||
native_format = fourcc;
|
||||
*fourccs = fourcc;
|
||||
++fourccs;
|
||||
}
|
||||
@ -918,17 +1113,14 @@ size_t drm_fb_build_fourcc_list(struct drm_device *dev,
|
||||
* The extra formats, emulated by the driver, go second.
|
||||
*/
|
||||
|
||||
for (i = 0; (i < driver_nfourccs) && (fourccs < fourccs_end); ++i) {
|
||||
u32 fourcc = driver_fourccs[i];
|
||||
for (i = 0; (i < extra_nfourccs) && (fourccs < fourccs_end); ++i) {
|
||||
u32 fourcc = extra_fourccs[i];
|
||||
|
||||
if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) {
|
||||
continue; /* skip duplicate and native entries */
|
||||
} else if (fourccs == fourccs_end) {
|
||||
drm_warn(dev, "Ignoring emulated format %p4cc\n", &fourcc);
|
||||
continue; /* end of available output buffer */
|
||||
} else if (!is_conversion_supported(fourcc, native_format)) {
|
||||
drm_dbg_kms(dev, "Unsupported emulated format %p4cc\n", &fourcc);
|
||||
continue; /* format is not supported for conversion */
|
||||
}
|
||||
|
||||
drm_dbg_kms(dev, "adding emulated format %p4cc\n", &fourcc);
|
||||
|
@ -477,8 +477,8 @@ drm_gem_dma_prime_import_sg_table(struct drm_device *dev,
|
||||
dma_obj->dma_addr = sg_dma_address(sgt->sgl);
|
||||
dma_obj->sgt = sgt;
|
||||
|
||||
DRM_DEBUG_PRIME("dma_addr = %pad, size = %zu\n", &dma_obj->dma_addr,
|
||||
attach->dmabuf->size);
|
||||
drm_dbg_prime(dev, "dma_addr = %pad, size = %zu\n", &dma_obj->dma_addr,
|
||||
attach->dmabuf->size);
|
||||
|
||||
return &dma_obj->base;
|
||||
}
|
||||
|
@ -766,7 +766,7 @@ drm_gem_shmem_prime_import_sg_table(struct drm_device *dev,
|
||||
|
||||
shmem->sgt = sgt;
|
||||
|
||||
DRM_DEBUG_PRIME("size = %zu\n", size);
|
||||
drm_dbg_prime(dev, "size = %zu\n", size);
|
||||
|
||||
return &shmem->base;
|
||||
}
|
||||
|
@ -972,6 +972,7 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
unsigned int nr = DRM_IOCTL_NR(cmd);
|
||||
struct drm_file *file_priv = filp->private_data;
|
||||
struct drm_device *dev = file_priv->minor->dev;
|
||||
drm_ioctl_compat_t *fn;
|
||||
int ret;
|
||||
|
||||
@ -986,14 +987,14 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
if (!fn)
|
||||
return drm_ioctl(filp, cmd, arg);
|
||||
|
||||
DRM_DEBUG("comm=\"%s\", pid=%d, dev=0x%lx, auth=%d, %s\n",
|
||||
current->comm, task_pid_nr(current),
|
||||
(long)old_encode_dev(file_priv->minor->kdev->devt),
|
||||
file_priv->authenticated,
|
||||
drm_compat_ioctls[nr].name);
|
||||
drm_dbg_core(dev, "comm=\"%s\", pid=%d, dev=0x%lx, auth=%d, %s\n",
|
||||
current->comm, task_pid_nr(current),
|
||||
(long)old_encode_dev(file_priv->minor->kdev->devt),
|
||||
file_priv->authenticated,
|
||||
drm_compat_ioctls[nr].name);
|
||||
ret = (*fn)(filp, cmd, arg);
|
||||
if (ret)
|
||||
DRM_DEBUG("ret = %d\n", ret);
|
||||
drm_dbg_core(dev, "ret = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_compat_ioctl);
|
||||
|
@ -440,7 +440,7 @@ done:
|
||||
int drm_noop(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
DRM_DEBUG("\n");
|
||||
drm_dbg_core(dev, "\n");
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_noop);
|
||||
@ -856,16 +856,16 @@ long drm_ioctl(struct file *filp,
|
||||
out_size = 0;
|
||||
ksize = max(max(in_size, out_size), drv_size);
|
||||
|
||||
DRM_DEBUG("comm=\"%s\" pid=%d, dev=0x%lx, auth=%d, %s\n",
|
||||
current->comm, task_pid_nr(current),
|
||||
(long)old_encode_dev(file_priv->minor->kdev->devt),
|
||||
file_priv->authenticated, ioctl->name);
|
||||
drm_dbg_core(dev, "comm=\"%s\" pid=%d, dev=0x%lx, auth=%d, %s\n",
|
||||
current->comm, task_pid_nr(current),
|
||||
(long)old_encode_dev(file_priv->minor->kdev->devt),
|
||||
file_priv->authenticated, ioctl->name);
|
||||
|
||||
/* Do not trust userspace, use our own definition */
|
||||
func = ioctl->func;
|
||||
|
||||
if (unlikely(!func)) {
|
||||
DRM_DEBUG("no function\n");
|
||||
drm_dbg_core(dev, "no function\n");
|
||||
retcode = -EINVAL;
|
||||
goto err_i1;
|
||||
}
|
||||
@ -894,16 +894,17 @@ long drm_ioctl(struct file *filp,
|
||||
|
||||
err_i1:
|
||||
if (!ioctl)
|
||||
DRM_DEBUG("invalid ioctl: comm=\"%s\", pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n",
|
||||
current->comm, task_pid_nr(current),
|
||||
(long)old_encode_dev(file_priv->minor->kdev->devt),
|
||||
file_priv->authenticated, cmd, nr);
|
||||
drm_dbg_core(dev,
|
||||
"invalid ioctl: comm=\"%s\", pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n",
|
||||
current->comm, task_pid_nr(current),
|
||||
(long)old_encode_dev(file_priv->minor->kdev->devt),
|
||||
file_priv->authenticated, cmd, nr);
|
||||
|
||||
if (kdata != stack_kdata)
|
||||
kfree(kdata);
|
||||
if (retcode)
|
||||
DRM_DEBUG("comm=\"%s\", pid=%d, ret=%d\n", current->comm,
|
||||
task_pid_nr(current), retcode);
|
||||
drm_dbg_core(dev, "comm=\"%s\", pid=%d, ret=%d\n",
|
||||
current->comm, task_pid_nr(current), retcode);
|
||||
return retcode;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_ioctl);
|
||||
|
@ -213,11 +213,11 @@ static struct drm_master *drm_lease_create(struct drm_master *lessor, struct idr
|
||||
int id;
|
||||
void *entry;
|
||||
|
||||
DRM_DEBUG_LEASE("lessor %d\n", lessor->lessee_id);
|
||||
drm_dbg_lease(dev, "lessor %d\n", lessor->lessee_id);
|
||||
|
||||
lessee = drm_master_create(lessor->dev);
|
||||
if (!lessee) {
|
||||
DRM_DEBUG_LEASE("drm_master_create failed\n");
|
||||
drm_dbg_lease(dev, "drm_master_create failed\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
@ -231,7 +231,7 @@ static struct drm_master *drm_lease_create(struct drm_master *lessor, struct idr
|
||||
error = -EBUSY;
|
||||
|
||||
if (error != 0) {
|
||||
DRM_DEBUG_LEASE("object %d failed %d\n", object, error);
|
||||
drm_dbg_lease(dev, "object %d failed %d\n", object, error);
|
||||
goto out_lessee;
|
||||
}
|
||||
}
|
||||
@ -249,7 +249,8 @@ static struct drm_master *drm_lease_create(struct drm_master *lessor, struct idr
|
||||
|
||||
/* Move the leases over */
|
||||
lessee->leases = *leases;
|
||||
DRM_DEBUG_LEASE("new lessee %d %p, lessor %d %p\n", lessee->lessee_id, lessee, lessor->lessee_id, lessor);
|
||||
drm_dbg_lease(dev, "new lessee %d %p, lessor %d %p\n",
|
||||
lessee->lessee_id, lessee, lessor->lessee_id, lessor);
|
||||
|
||||
mutex_unlock(&dev->mode_config.idr_mutex);
|
||||
return lessee;
|
||||
@ -268,7 +269,7 @@ void drm_lease_destroy(struct drm_master *master)
|
||||
|
||||
mutex_lock(&dev->mode_config.idr_mutex);
|
||||
|
||||
DRM_DEBUG_LEASE("drm_lease_destroy %d\n", master->lessee_id);
|
||||
drm_dbg_lease(dev, "drm_lease_destroy %d\n", master->lessee_id);
|
||||
|
||||
/* This master is referenced by all lessees, hence it cannot be destroyed
|
||||
* until all of them have been
|
||||
@ -277,7 +278,8 @@ void drm_lease_destroy(struct drm_master *master)
|
||||
|
||||
/* Remove this master from the lessee idr in the owner */
|
||||
if (master->lessee_id != 0) {
|
||||
DRM_DEBUG_LEASE("remove master %d from device list of lessees\n", master->lessee_id);
|
||||
drm_dbg_lease(dev, "remove master %d from device list of lessees\n",
|
||||
master->lessee_id);
|
||||
idr_remove(&(drm_lease_owner(master)->lessee_idr), master->lessee_id);
|
||||
}
|
||||
|
||||
@ -292,7 +294,7 @@ void drm_lease_destroy(struct drm_master *master)
|
||||
drm_master_put(&master->lessor);
|
||||
}
|
||||
|
||||
DRM_DEBUG_LEASE("drm_lease_destroy done %d\n", master->lessee_id);
|
||||
drm_dbg_lease(dev, "drm_lease_destroy done %d\n", master->lessee_id);
|
||||
}
|
||||
|
||||
static void _drm_lease_revoke(struct drm_master *top)
|
||||
@ -308,7 +310,8 @@ static void _drm_lease_revoke(struct drm_master *top)
|
||||
* the tree is fully connected, we can do this without recursing
|
||||
*/
|
||||
for (;;) {
|
||||
DRM_DEBUG_LEASE("revoke leases for %p %d\n", master, master->lessee_id);
|
||||
drm_dbg_lease(master->dev, "revoke leases for %p %d\n",
|
||||
master, master->lessee_id);
|
||||
|
||||
/* Evacuate the lease */
|
||||
idr_for_each_entry(&master->leases, entry, object)
|
||||
@ -408,7 +411,7 @@ static int fill_object_idr(struct drm_device *dev,
|
||||
|
||||
ret = validate_lease(dev, object_count, objects, universal_planes);
|
||||
if (ret) {
|
||||
DRM_DEBUG_LEASE("lease validation failed\n");
|
||||
drm_dbg_lease(dev, "lease validation failed\n");
|
||||
goto out_free_objects;
|
||||
}
|
||||
|
||||
@ -418,7 +421,7 @@ static int fill_object_idr(struct drm_device *dev,
|
||||
struct drm_mode_object *obj = objects[o];
|
||||
u32 object_id = objects[o]->id;
|
||||
|
||||
DRM_DEBUG_LEASE("Adding object %d to lease\n", object_id);
|
||||
drm_dbg_lease(dev, "Adding object %d to lease\n", object_id);
|
||||
|
||||
/*
|
||||
* We're using an IDR to hold the set of leased
|
||||
@ -430,8 +433,8 @@ static int fill_object_idr(struct drm_device *dev,
|
||||
*/
|
||||
ret = idr_alloc(leases, &drm_lease_idr_object , object_id, object_id + 1, GFP_KERNEL);
|
||||
if (ret < 0) {
|
||||
DRM_DEBUG_LEASE("Object %d cannot be inserted into leases (%d)\n",
|
||||
object_id, ret);
|
||||
drm_dbg_lease(dev, "Object %d cannot be inserted into leases (%d)\n",
|
||||
object_id, ret);
|
||||
goto out_free_objects;
|
||||
}
|
||||
if (obj->type == DRM_MODE_OBJECT_CRTC && !universal_planes) {
|
||||
@ -439,15 +442,15 @@ static int fill_object_idr(struct drm_device *dev,
|
||||
|
||||
ret = idr_alloc(leases, &drm_lease_idr_object, crtc->primary->base.id, crtc->primary->base.id + 1, GFP_KERNEL);
|
||||
if (ret < 0) {
|
||||
DRM_DEBUG_LEASE("Object primary plane %d cannot be inserted into leases (%d)\n",
|
||||
object_id, ret);
|
||||
drm_dbg_lease(dev, "Object primary plane %d cannot be inserted into leases (%d)\n",
|
||||
object_id, ret);
|
||||
goto out_free_objects;
|
||||
}
|
||||
if (crtc->cursor) {
|
||||
ret = idr_alloc(leases, &drm_lease_idr_object, crtc->cursor->base.id, crtc->cursor->base.id + 1, GFP_KERNEL);
|
||||
if (ret < 0) {
|
||||
DRM_DEBUG_LEASE("Object cursor plane %d cannot be inserted into leases (%d)\n",
|
||||
object_id, ret);
|
||||
drm_dbg_lease(dev, "Object cursor plane %d cannot be inserted into leases (%d)\n",
|
||||
object_id, ret);
|
||||
goto out_free_objects;
|
||||
}
|
||||
}
|
||||
@ -490,14 +493,14 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (cl->flags && (cl->flags & ~(O_CLOEXEC | O_NONBLOCK))) {
|
||||
DRM_DEBUG_LEASE("invalid flags\n");
|
||||
drm_dbg_lease(dev, "invalid flags\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
lessor = drm_file_get_master(lessor_priv);
|
||||
/* Do not allow sub-leases */
|
||||
if (lessor->lessor) {
|
||||
DRM_DEBUG_LEASE("recursive leasing not allowed\n");
|
||||
drm_dbg_lease(dev, "recursive leasing not allowed\n");
|
||||
ret = -EINVAL;
|
||||
goto out_lessor;
|
||||
}
|
||||
@ -520,7 +523,7 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
|
||||
object_count, object_ids);
|
||||
kfree(object_ids);
|
||||
if (ret) {
|
||||
DRM_DEBUG_LEASE("lease object lookup failed: %i\n", ret);
|
||||
drm_dbg_lease(dev, "lease object lookup failed: %i\n", ret);
|
||||
idr_destroy(&leases);
|
||||
goto out_lessor;
|
||||
}
|
||||
@ -534,7 +537,7 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
|
||||
goto out_lessor;
|
||||
}
|
||||
|
||||
DRM_DEBUG_LEASE("Creating lease\n");
|
||||
drm_dbg_lease(dev, "Creating lease\n");
|
||||
/* lessee will take the ownership of leases */
|
||||
lessee = drm_lease_create(lessor, &leases);
|
||||
|
||||
@ -545,7 +548,7 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
|
||||
}
|
||||
|
||||
/* Clone the lessor file to create a new file for us */
|
||||
DRM_DEBUG_LEASE("Allocating lease file\n");
|
||||
drm_dbg_lease(dev, "Allocating lease file\n");
|
||||
lessee_file = file_clone_open(lessor_file);
|
||||
if (IS_ERR(lessee_file)) {
|
||||
ret = PTR_ERR(lessee_file);
|
||||
@ -560,7 +563,7 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
|
||||
lessee_priv->authenticated = 1;
|
||||
|
||||
/* Pass fd back to userspace */
|
||||
DRM_DEBUG_LEASE("Returning fd %d id %d\n", fd, lessee->lessee_id);
|
||||
drm_dbg_lease(dev, "Returning fd %d id %d\n", fd, lessee->lessee_id);
|
||||
cl->fd = fd;
|
||||
cl->lessee_id = lessee->lessee_id;
|
||||
|
||||
@ -568,7 +571,7 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
|
||||
fd_install(fd, lessee_file);
|
||||
|
||||
drm_master_put(&lessor);
|
||||
DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl succeeded\n");
|
||||
drm_dbg_lease(dev, "drm_mode_create_lease_ioctl succeeded\n");
|
||||
return 0;
|
||||
|
||||
out_lessee:
|
||||
@ -579,7 +582,7 @@ out_leases:
|
||||
|
||||
out_lessor:
|
||||
drm_master_put(&lessor);
|
||||
DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl failed: %d\n", ret);
|
||||
drm_dbg_lease(dev, "drm_mode_create_lease_ioctl failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -601,7 +604,7 @@ int drm_mode_list_lessees_ioctl(struct drm_device *dev,
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
lessor = drm_file_get_master(lessor_priv);
|
||||
DRM_DEBUG_LEASE("List lessees for %d\n", lessor->lessee_id);
|
||||
drm_dbg_lease(dev, "List lessees for %d\n", lessor->lessee_id);
|
||||
|
||||
mutex_lock(&dev->mode_config.idr_mutex);
|
||||
|
||||
@ -610,7 +613,8 @@ int drm_mode_list_lessees_ioctl(struct drm_device *dev,
|
||||
/* Only list un-revoked leases */
|
||||
if (!idr_is_empty(&lessee->leases)) {
|
||||
if (count_lessees > count) {
|
||||
DRM_DEBUG_LEASE("Add lessee %d\n", lessee->lessee_id);
|
||||
drm_dbg_lease(dev, "Add lessee %d\n",
|
||||
lessee->lessee_id);
|
||||
ret = put_user(lessee->lessee_id, lessee_ids + count);
|
||||
if (ret)
|
||||
break;
|
||||
@ -619,7 +623,7 @@ int drm_mode_list_lessees_ioctl(struct drm_device *dev,
|
||||
}
|
||||
}
|
||||
|
||||
DRM_DEBUG_LEASE("Lessor leases to %d\n", count);
|
||||
drm_dbg_lease(dev, "Lessor leases to %d\n", count);
|
||||
if (ret == 0)
|
||||
arg->count_lessees = count;
|
||||
|
||||
@ -651,7 +655,7 @@ int drm_mode_get_lease_ioctl(struct drm_device *dev,
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
lessee = drm_file_get_master(lessee_priv);
|
||||
DRM_DEBUG_LEASE("get lease for %d\n", lessee->lessee_id);
|
||||
drm_dbg_lease(dev, "get lease for %d\n", lessee->lessee_id);
|
||||
|
||||
mutex_lock(&dev->mode_config.idr_mutex);
|
||||
|
||||
@ -665,7 +669,7 @@ int drm_mode_get_lease_ioctl(struct drm_device *dev,
|
||||
count = 0;
|
||||
idr_for_each_entry(object_idr, entry, object) {
|
||||
if (count_objects > count) {
|
||||
DRM_DEBUG_LEASE("adding object %d\n", object);
|
||||
drm_dbg_lease(dev, "adding object %d\n", object);
|
||||
ret = put_user(object, object_ids + count);
|
||||
if (ret)
|
||||
break;
|
||||
@ -696,7 +700,7 @@ int drm_mode_revoke_lease_ioctl(struct drm_device *dev,
|
||||
struct drm_master *lessee;
|
||||
int ret = 0;
|
||||
|
||||
DRM_DEBUG_LEASE("revoke lease for %d\n", arg->lessee_id);
|
||||
drm_dbg_lease(dev, "revoke lease for %d\n", arg->lessee_id);
|
||||
|
||||
/* Can't lease without MODESET */
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
|
@ -46,6 +46,11 @@
|
||||
* properties that specify how the pixels are positioned and blended, like
|
||||
* rotation or Z-position. All these properties are stored in &drm_plane_state.
|
||||
*
|
||||
* Unless explicitly specified (via CRTC property or otherwise), the active area
|
||||
* of a CRTC will be black by default. This means portions of the active area
|
||||
* which are not covered by a plane will be black, and alpha blending of any
|
||||
* planes with the CRTC background will blend with black at the lowest zpos.
|
||||
*
|
||||
* To create a plane, a KMS drivers allocates and zeroes an instances of
|
||||
* &struct drm_plane (possibly as part of a larger structure) and registers it
|
||||
* with a call to drm_universal_plane_init().
|
||||
|
@ -250,6 +250,12 @@ void drm_kms_helper_poll_enable(struct drm_device *dev)
|
||||
|
||||
drm_connector_list_iter_begin(dev, &conn_iter);
|
||||
drm_for_each_connector_iter(connector, &conn_iter) {
|
||||
const struct drm_connector_helper_funcs *funcs =
|
||||
connector->helper_private;
|
||||
|
||||
if (funcs && funcs->enable_hpd)
|
||||
funcs->enable_hpd(connector);
|
||||
|
||||
if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT |
|
||||
DRM_CONNECTOR_POLL_DISCONNECT))
|
||||
poll = true;
|
||||
@ -802,6 +808,30 @@ bool drm_kms_helper_is_poll_worker(void)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_kms_helper_is_poll_worker);
|
||||
|
||||
static void drm_kms_helper_poll_disable_fini(struct drm_device *dev, bool fini)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
|
||||
if (!dev->mode_config.poll_enabled)
|
||||
return;
|
||||
|
||||
if (fini)
|
||||
dev->mode_config.poll_enabled = false;
|
||||
|
||||
drm_connector_list_iter_begin(dev, &conn_iter);
|
||||
drm_for_each_connector_iter(connector, &conn_iter) {
|
||||
const struct drm_connector_helper_funcs *funcs =
|
||||
connector->helper_private;
|
||||
|
||||
if (funcs && funcs->disable_hpd)
|
||||
funcs->disable_hpd(connector);
|
||||
}
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
|
||||
cancel_delayed_work_sync(&dev->mode_config.output_poll_work);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_kms_helper_poll_disable - disable output polling
|
||||
* @dev: drm_device
|
||||
@ -818,9 +848,7 @@ EXPORT_SYMBOL(drm_kms_helper_is_poll_worker);
|
||||
*/
|
||||
void drm_kms_helper_poll_disable(struct drm_device *dev)
|
||||
{
|
||||
if (!dev->mode_config.poll_enabled)
|
||||
return;
|
||||
cancel_delayed_work_sync(&dev->mode_config.output_poll_work);
|
||||
drm_kms_helper_poll_disable_fini(dev, false);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_kms_helper_poll_disable);
|
||||
|
||||
@ -858,11 +886,7 @@ EXPORT_SYMBOL(drm_kms_helper_poll_init);
|
||||
*/
|
||||
void drm_kms_helper_poll_fini(struct drm_device *dev)
|
||||
{
|
||||
if (!dev->mode_config.poll_enabled)
|
||||
return;
|
||||
|
||||
dev->mode_config.poll_enabled = false;
|
||||
cancel_delayed_work_sync(&dev->mode_config.output_poll_work);
|
||||
drm_kms_helper_poll_disable_fini(dev, true);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_kms_helper_poll_fini);
|
||||
|
||||
|
@ -3,6 +3,8 @@ config DRM_GMA500
|
||||
tristate "Intel GMA500/600/3600/3650 KMS Framebuffer"
|
||||
depends on DRM && PCI && X86 && MMU
|
||||
select DRM_KMS_HELPER
|
||||
select I2C
|
||||
select I2C_ALGOBIT
|
||||
# GMA500 depends on ACPI_VIDEO when ACPI is enabled, just like i915
|
||||
select ACPI_VIDEO if ACPI
|
||||
select BACKLIGHT_CLASS_DEVICE if ACPI
|
||||
|
@ -325,8 +325,8 @@ static struct drm_gem_object *gud_gem_prime_import(struct drm_device *drm, struc
|
||||
|
||||
static int gud_stats_debugfs(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_info_node *node = m->private;
|
||||
struct gud_device *gdrm = to_gud_device(node->minor->dev);
|
||||
struct drm_debugfs_entry *entry = m->private;
|
||||
struct gud_device *gdrm = to_gud_device(entry->dev);
|
||||
char buf[10];
|
||||
|
||||
string_get_size(gdrm->bulk_len, 1, STRING_UNITS_2, buf, sizeof(buf));
|
||||
@ -352,16 +352,6 @@ static int gud_stats_debugfs(struct seq_file *m, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_info_list gud_debugfs_list[] = {
|
||||
{ "stats", gud_stats_debugfs, 0, NULL },
|
||||
};
|
||||
|
||||
static void gud_debugfs_init(struct drm_minor *minor)
|
||||
{
|
||||
drm_debugfs_create_files(gud_debugfs_list, ARRAY_SIZE(gud_debugfs_list),
|
||||
minor->debugfs_root, minor);
|
||||
}
|
||||
|
||||
static const struct drm_simple_display_pipe_funcs gud_pipe_funcs = {
|
||||
.check = gud_pipe_check,
|
||||
.update = gud_pipe_update,
|
||||
@ -386,7 +376,6 @@ static const struct drm_driver gud_drm_driver = {
|
||||
.fops = &gud_fops,
|
||||
DRM_GEM_SHMEM_DRIVER_OPS,
|
||||
.gem_prime_import = gud_gem_prime_import,
|
||||
.debugfs_init = gud_debugfs_init,
|
||||
|
||||
.name = "gud",
|
||||
.desc = "Generic USB Display",
|
||||
@ -623,6 +612,8 @@ static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
if (!gdrm->dmadev)
|
||||
dev_warn(dev, "buffer sharing not supported");
|
||||
|
||||
drm_debugfs_add_file(drm, "stats", gud_stats_debugfs, NULL);
|
||||
|
||||
ret = drm_dev_register(drm, 0);
|
||||
if (ret) {
|
||||
put_device(gdrm->dmadev);
|
||||
|
@ -7,6 +7,8 @@ config DRM_HISI_HIBMC
|
||||
select DRM_VRAM_HELPER
|
||||
select DRM_TTM
|
||||
select DRM_TTM_HELPER
|
||||
select I2C
|
||||
select I2C_ALGOBIT
|
||||
help
|
||||
Choose this option if you have a Hisilicon Hibmc soc chipset.
|
||||
If M is selected the module will be called hibmc-drm.
|
||||
|
@ -386,7 +386,7 @@ static const struct drm_encoder_slave_funcs ch7006_encoder_funcs = {
|
||||
|
||||
/* I2C driver functions */
|
||||
|
||||
static int ch7006_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
static int ch7006_probe(struct i2c_client *client)
|
||||
{
|
||||
uint8_t addr = CH7006_VERSION_ID;
|
||||
uint8_t val;
|
||||
@ -495,7 +495,7 @@ static const struct dev_pm_ops ch7006_pm_ops = {
|
||||
|
||||
static struct drm_i2c_encoder_driver ch7006_driver = {
|
||||
.i2c_driver = {
|
||||
.probe = ch7006_probe,
|
||||
.probe_new = ch7006_probe,
|
||||
.remove = ch7006_remove,
|
||||
|
||||
.driver = {
|
||||
|
@ -350,7 +350,7 @@ static const struct drm_encoder_slave_funcs sil164_encoder_funcs = {
|
||||
/* I2C driver functions */
|
||||
|
||||
static int
|
||||
sil164_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
sil164_probe(struct i2c_client *client)
|
||||
{
|
||||
int vendor = sil164_read(client, SIL164_VENDOR_HI) << 8 |
|
||||
sil164_read(client, SIL164_VENDOR_LO);
|
||||
@ -420,7 +420,7 @@ MODULE_DEVICE_TABLE(i2c, sil164_ids);
|
||||
|
||||
static struct drm_i2c_encoder_driver sil164_driver = {
|
||||
.i2c_driver = {
|
||||
.probe = sil164_probe,
|
||||
.probe_new = sil164_probe,
|
||||
.driver = {
|
||||
.name = "sil164",
|
||||
},
|
||||
|
@ -375,8 +375,7 @@ static void tda9950_cec_del(void *data)
|
||||
cec_delete_adapter(priv->adap);
|
||||
}
|
||||
|
||||
static int tda9950_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int tda9950_probe(struct i2c_client *client)
|
||||
{
|
||||
struct tda9950_glue *glue = client->dev.platform_data;
|
||||
struct device *dev = &client->dev;
|
||||
@ -493,7 +492,7 @@ static struct i2c_device_id tda9950_ids[] = {
|
||||
MODULE_DEVICE_TABLE(i2c, tda9950_ids);
|
||||
|
||||
static struct i2c_driver tda9950_driver = {
|
||||
.probe = tda9950_probe,
|
||||
.probe_new = tda9950_probe,
|
||||
.remove = tda9950_remove,
|
||||
.driver = {
|
||||
.name = "tda9950",
|
||||
|
@ -2059,7 +2059,7 @@ static const struct component_ops tda998x_ops = {
|
||||
};
|
||||
|
||||
static int
|
||||
tda998x_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
tda998x_probe(struct i2c_client *client)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -2099,7 +2099,7 @@ static const struct i2c_device_id tda998x_ids[] = {
|
||||
MODULE_DEVICE_TABLE(i2c, tda998x_ids);
|
||||
|
||||
static struct i2c_driver tda998x_driver = {
|
||||
.probe = tda998x_probe,
|
||||
.probe_new = tda998x_probe,
|
||||
.remove = tda998x_remove,
|
||||
.driver = {
|
||||
.name = "tda998x",
|
||||
|
@ -18,6 +18,8 @@ config DRM_I915
|
||||
select DRM_PANEL
|
||||
select DRM_MIPI_DSI
|
||||
select RELAY
|
||||
select I2C
|
||||
select I2C_ALGOBIT
|
||||
select IRQ_WORK
|
||||
# i915 depends on ACPI_VIDEO when ACPI is enabled
|
||||
# but for select to work, need to select ACPI_VIDEO's dependencies, ick
|
||||
|
@ -253,11 +253,8 @@ static int dcss_dev_suspend(struct device *dev)
|
||||
{
|
||||
struct dcss_dev *dcss = dcss_drv_dev_to_dcss(dev);
|
||||
struct drm_device *ddev = dcss_drv_dev_to_drm(dev);
|
||||
struct dcss_kms_dev *kms = container_of(ddev, struct dcss_kms_dev, base);
|
||||
int ret;
|
||||
|
||||
drm_bridge_connector_disable_hpd(kms->connector);
|
||||
|
||||
drm_mode_config_helper_suspend(ddev);
|
||||
|
||||
if (pm_runtime_suspended(dev))
|
||||
@ -276,7 +273,6 @@ static int dcss_dev_resume(struct device *dev)
|
||||
{
|
||||
struct dcss_dev *dcss = dcss_drv_dev_to_dcss(dev);
|
||||
struct drm_device *ddev = dcss_drv_dev_to_drm(dev);
|
||||
struct dcss_kms_dev *kms = container_of(ddev, struct dcss_kms_dev, base);
|
||||
|
||||
if (pm_runtime_suspended(dev)) {
|
||||
drm_mode_config_helper_resume(ddev);
|
||||
@ -291,8 +287,6 @@ static int dcss_dev_resume(struct device *dev)
|
||||
|
||||
drm_mode_config_helper_resume(ddev);
|
||||
|
||||
drm_bridge_connector_enable_hpd(kms->connector);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -74,8 +74,6 @@ static int dcss_drv_platform_probe(struct platform_device *pdev)
|
||||
dcss_shutoff:
|
||||
dcss_dev_destroy(mdrv->dcss);
|
||||
|
||||
dev_set_drvdata(dev, NULL);
|
||||
|
||||
err:
|
||||
kfree(mdrv);
|
||||
return err;
|
||||
@ -85,14 +83,9 @@ static int dcss_drv_platform_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct dcss_drv *mdrv = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
if (!mdrv)
|
||||
return 0;
|
||||
|
||||
dcss_kms_detach(mdrv->kms);
|
||||
dcss_dev_destroy(mdrv->dcss);
|
||||
|
||||
dev_set_drvdata(&pdev->dev, NULL);
|
||||
|
||||
kfree(mdrv);
|
||||
|
||||
return 0;
|
||||
|
@ -150,7 +150,6 @@ struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss)
|
||||
return kms;
|
||||
|
||||
cleanup_crtc:
|
||||
drm_bridge_connector_disable_hpd(kms->connector);
|
||||
drm_kms_helper_poll_fini(drm);
|
||||
dcss_crtc_deinit(crtc, drm);
|
||||
|
||||
@ -166,7 +165,6 @@ void dcss_kms_detach(struct dcss_kms_dev *kms)
|
||||
struct drm_device *drm = &kms->base;
|
||||
|
||||
drm_dev_unregister(drm);
|
||||
drm_bridge_connector_disable_hpd(kms->connector);
|
||||
drm_kms_helper_poll_fini(drm);
|
||||
drm_atomic_helper_shutdown(drm);
|
||||
drm_crtc_vblank_off(&kms->crtc.base);
|
||||
|
@ -718,7 +718,7 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
|
||||
dw_plat_data = &meson_dw_hdmi->dw_plat_data;
|
||||
|
||||
ret = devm_regulator_get_enable_optional(dev, "hdmi");
|
||||
if (ret != -ENODEV)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
meson_dw_hdmi->hdmitx_apb = devm_reset_control_get_exclusive(dev,
|
||||
|
@ -4,6 +4,8 @@ config DRM_MGAG200
|
||||
depends on DRM && PCI && MMU
|
||||
select DRM_GEM_SHMEM_HELPER
|
||||
select DRM_KMS_HELPER
|
||||
select I2C
|
||||
select I2C_ALGOBIT
|
||||
help
|
||||
This is a KMS driver for Matrox G200 chips. It supports the original
|
||||
MGA G200 desktop chips and the server variants. It requires 0.3.0
|
||||
|
@ -203,8 +203,6 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
drm_bridge_connector_enable_hpd(hdmi->connector);
|
||||
|
||||
ret = msm_hdmi_hpd_enable(hdmi->bridge);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(&hdmi->pdev->dev, "failed to enable HPD: %d\n", ret);
|
||||
|
@ -78,14 +78,12 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
|
||||
|
||||
void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb)
|
||||
{
|
||||
if (mxsfb->clk_axi)
|
||||
clk_prepare_enable(mxsfb->clk_axi);
|
||||
clk_prepare_enable(mxsfb->clk_axi);
|
||||
}
|
||||
|
||||
void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb)
|
||||
{
|
||||
if (mxsfb->clk_axi)
|
||||
clk_disable_unprepare(mxsfb->clk_axi);
|
||||
clk_disable_unprepare(mxsfb->clk_axi);
|
||||
}
|
||||
|
||||
static struct drm_framebuffer *
|
||||
@ -235,9 +233,9 @@ static int mxsfb_load(struct drm_device *drm,
|
||||
if (IS_ERR(mxsfb->clk))
|
||||
return PTR_ERR(mxsfb->clk);
|
||||
|
||||
mxsfb->clk_axi = devm_clk_get(drm->dev, "axi");
|
||||
mxsfb->clk_axi = devm_clk_get_optional(drm->dev, "axi");
|
||||
if (IS_ERR(mxsfb->clk_axi))
|
||||
mxsfb->clk_axi = NULL;
|
||||
return PTR_ERR(mxsfb->clk_axi);
|
||||
|
||||
mxsfb->clk_disp_axi = devm_clk_get(drm->dev, "disp_axi");
|
||||
if (IS_ERR(mxsfb->clk_disp_axi))
|
||||
|
@ -10,6 +10,8 @@ config DRM_NOUVEAU
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_TTM
|
||||
select DRM_TTM_HELPER
|
||||
select I2C
|
||||
select I2C_ALGOBIT
|
||||
select BACKLIGHT_CLASS_DEVICE if DRM_NOUVEAU_BACKLIGHT
|
||||
select X86_PLATFORM_DEVICES if ACPI && X86
|
||||
select ACPI_WMI if ACPI && X86
|
||||
|
@ -545,44 +545,6 @@ static void omap_modeset_fini(struct drm_device *ddev)
|
||||
drm_mode_config_cleanup(ddev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable the HPD in external components if supported
|
||||
*/
|
||||
static void omap_modeset_enable_external_hpd(struct drm_device *ddev)
|
||||
{
|
||||
struct omap_drm_private *priv = ddev->dev_private;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < priv->num_pipes; i++) {
|
||||
struct drm_connector *connector = priv->pipes[i].connector;
|
||||
|
||||
if (!connector)
|
||||
continue;
|
||||
|
||||
if (priv->pipes[i].output->bridge)
|
||||
drm_bridge_connector_enable_hpd(connector);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable the HPD in external components if supported
|
||||
*/
|
||||
static void omap_modeset_disable_external_hpd(struct drm_device *ddev)
|
||||
{
|
||||
struct omap_drm_private *priv = ddev->dev_private;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < priv->num_pipes; i++) {
|
||||
struct drm_connector *connector = priv->pipes[i].connector;
|
||||
|
||||
if (!connector)
|
||||
continue;
|
||||
|
||||
if (priv->pipes[i].output->bridge)
|
||||
drm_bridge_connector_disable_hpd(connector);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* drm ioctl funcs
|
||||
*/
|
||||
@ -782,7 +744,6 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev)
|
||||
omap_fbdev_init(ddev);
|
||||
|
||||
drm_kms_helper_poll_init(ddev);
|
||||
omap_modeset_enable_external_hpd(ddev);
|
||||
|
||||
/*
|
||||
* Register the DRM device with the core and the connectors with
|
||||
@ -795,7 +756,6 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev)
|
||||
return 0;
|
||||
|
||||
err_cleanup_helpers:
|
||||
omap_modeset_disable_external_hpd(ddev);
|
||||
drm_kms_helper_poll_fini(ddev);
|
||||
|
||||
omap_fbdev_fini(ddev);
|
||||
@ -822,7 +782,6 @@ static void omapdrm_cleanup(struct omap_drm_private *priv)
|
||||
|
||||
drm_dev_unregister(ddev);
|
||||
|
||||
omap_modeset_disable_external_hpd(ddev);
|
||||
drm_kms_helper_poll_fini(ddev);
|
||||
|
||||
omap_fbdev_fini(ddev);
|
||||
|
@ -154,6 +154,18 @@ config DRM_PANEL_FEIYANG_FY07024DI26A30D
|
||||
Say Y if you want to enable support for panels based on the
|
||||
Feiyang FY07024DI26A30-D MIPI-DSI interface.
|
||||
|
||||
config DRM_PANEL_HIMAX_HX8394
|
||||
tristate "HIMAX HX8394 MIPI-DSI LCD panels"
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
help
|
||||
Say Y if you want to enable support for panels based on the
|
||||
Himax HX8394 controller, such as the HannStar HSD060BHW4
|
||||
720x1440 TFT LCD panel that uses a MIPI-DSI interface.
|
||||
|
||||
If M is selected the module will be called panel-himax-hx8394.
|
||||
|
||||
config DRM_PANEL_ILITEK_IL9322
|
||||
tristate "Ilitek ILI9322 320x240 QVGA panels"
|
||||
depends on OF && SPI
|
||||
@ -726,6 +738,14 @@ config DRM_PANEL_VISIONOX_RM69299
|
||||
Say Y here if you want to enable support for Visionox
|
||||
RM69299 DSI Video Mode panel.
|
||||
|
||||
config DRM_PANEL_VISIONOX_VTDR6130
|
||||
tristate "Visionox VTDR6130"
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
help
|
||||
Say Y here if you want to enable support for Visionox
|
||||
VTDR6130 1080x2400 AMOLED DSI panel.
|
||||
|
||||
config DRM_PANEL_WIDECHIPS_WS2401
|
||||
tristate "Widechips WS2401 DPI panel driver"
|
||||
depends on SPI && GPIOLIB
|
||||
|
@ -13,6 +13,7 @@ obj-$(CONFIG_DRM_PANEL_EBBG_FT8719) += panel-ebbg-ft8719.o
|
||||
obj-$(CONFIG_DRM_PANEL_ELIDA_KD35T133) += panel-elida-kd35t133.o
|
||||
obj-$(CONFIG_DRM_PANEL_FEIXIN_K101_IM2BA02) += panel-feixin-k101-im2ba02.o
|
||||
obj-$(CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D) += panel-feiyang-fy07024di26a30d.o
|
||||
obj-$(CONFIG_DRM_PANEL_HIMAX_HX8394) += panel-himax-hx8394.o
|
||||
obj-$(CONFIG_DRM_PANEL_ILITEK_IL9322) += panel-ilitek-ili9322.o
|
||||
obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9341) += panel-ilitek-ili9341.o
|
||||
obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9881C) += panel-ilitek-ili9881c.o
|
||||
@ -74,5 +75,6 @@ obj-$(CONFIG_DRM_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
|
||||
obj-$(CONFIG_DRM_PANEL_TPO_TPG110) += panel-tpo-tpg110.o
|
||||
obj-$(CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA) += panel-truly-nt35597.o
|
||||
obj-$(CONFIG_DRM_PANEL_VISIONOX_RM69299) += panel-visionox-rm69299.o
|
||||
obj-$(CONFIG_DRM_PANEL_VISIONOX_VTDR6130) += panel-visionox-vtdr6130.o
|
||||
obj-$(CONFIG_DRM_PANEL_WIDECHIPS_WS2401) += panel-widechips-ws2401.o
|
||||
obj-$(CONFIG_DRM_PANEL_XINPENG_XPP055C272) += panel-xinpeng-xpp055c272.o
|
||||
|
@ -24,22 +24,6 @@ static inline struct tm5p5_nt35596 *to_tm5p5_nt35596(struct drm_panel *panel)
|
||||
return container_of(panel, struct tm5p5_nt35596, panel);
|
||||
}
|
||||
|
||||
#define dsi_generic_write_seq(dsi, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
#define dsi_dcs_write_seq(dsi, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
static void tm5p5_nt35596_reset(struct tm5p5_nt35596 *ctx)
|
||||
{
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
@ -54,46 +38,46 @@ static int tm5p5_nt35596_on(struct tm5p5_nt35596 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
|
||||
dsi_generic_write_seq(dsi, 0xff, 0x05);
|
||||
dsi_generic_write_seq(dsi, 0xfb, 0x01);
|
||||
dsi_generic_write_seq(dsi, 0xc5, 0x31);
|
||||
dsi_generic_write_seq(dsi, 0xff, 0x04);
|
||||
dsi_generic_write_seq(dsi, 0x01, 0x84);
|
||||
dsi_generic_write_seq(dsi, 0x05, 0x25);
|
||||
dsi_generic_write_seq(dsi, 0x06, 0x01);
|
||||
dsi_generic_write_seq(dsi, 0x07, 0x20);
|
||||
dsi_generic_write_seq(dsi, 0x08, 0x06);
|
||||
dsi_generic_write_seq(dsi, 0x09, 0x08);
|
||||
dsi_generic_write_seq(dsi, 0x0a, 0x10);
|
||||
dsi_generic_write_seq(dsi, 0x0b, 0x10);
|
||||
dsi_generic_write_seq(dsi, 0x0c, 0x10);
|
||||
dsi_generic_write_seq(dsi, 0x0d, 0x14);
|
||||
dsi_generic_write_seq(dsi, 0x0e, 0x14);
|
||||
dsi_generic_write_seq(dsi, 0x0f, 0x14);
|
||||
dsi_generic_write_seq(dsi, 0x10, 0x14);
|
||||
dsi_generic_write_seq(dsi, 0x11, 0x14);
|
||||
dsi_generic_write_seq(dsi, 0x12, 0x14);
|
||||
dsi_generic_write_seq(dsi, 0x17, 0xf3);
|
||||
dsi_generic_write_seq(dsi, 0x18, 0xc0);
|
||||
dsi_generic_write_seq(dsi, 0x19, 0xc0);
|
||||
dsi_generic_write_seq(dsi, 0x1a, 0xc0);
|
||||
dsi_generic_write_seq(dsi, 0x1b, 0xb3);
|
||||
dsi_generic_write_seq(dsi, 0x1c, 0xb3);
|
||||
dsi_generic_write_seq(dsi, 0x1d, 0xb3);
|
||||
dsi_generic_write_seq(dsi, 0x1e, 0xb3);
|
||||
dsi_generic_write_seq(dsi, 0x1f, 0xb3);
|
||||
dsi_generic_write_seq(dsi, 0x20, 0xb3);
|
||||
dsi_generic_write_seq(dsi, 0xfb, 0x01);
|
||||
dsi_generic_write_seq(dsi, 0xff, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xfb, 0x01);
|
||||
dsi_generic_write_seq(dsi, 0x35, 0x01);
|
||||
dsi_generic_write_seq(dsi, 0xd3, 0x06);
|
||||
dsi_generic_write_seq(dsi, 0xd4, 0x04);
|
||||
dsi_generic_write_seq(dsi, 0x5e, 0x0d);
|
||||
dsi_generic_write_seq(dsi, 0x11, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xff, 0x05);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xfb, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc5, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xff, 0x04);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x01, 0x84);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x05, 0x25);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x06, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x07, 0x20);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x08, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x09, 0x08);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x0a, 0x10);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x0b, 0x10);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x0c, 0x10);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x0d, 0x14);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x0e, 0x14);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x0f, 0x14);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x10, 0x14);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x11, 0x14);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x12, 0x14);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x17, 0xf3);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x18, 0xc0);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x19, 0xc0);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x1a, 0xc0);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x1b, 0xb3);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x1c, 0xb3);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x1d, 0xb3);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x1e, 0xb3);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x1f, 0xb3);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x20, 0xb3);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xfb, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xff, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xfb, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x35, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd3, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd4, 0x04);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x5e, 0x0d);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x11, 0x00);
|
||||
msleep(100);
|
||||
dsi_generic_write_seq(dsi, 0x29, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0x53, 0x24);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x29, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x53, 0x24);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -117,7 +101,7 @@ static int tm5p5_nt35596_off(struct tm5p5_nt35596 *ctx)
|
||||
return ret;
|
||||
}
|
||||
|
||||
dsi_dcs_write_seq(dsi, 0x4f, 0x01);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0x4f, 0x01);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -43,14 +43,6 @@ struct boe_bf060y8m_aj0 *to_boe_bf060y8m_aj0(struct drm_panel *panel)
|
||||
return container_of(panel, struct boe_bf060y8m_aj0, panel);
|
||||
}
|
||||
|
||||
#define dsi_dcs_write_seq(dsi, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
static void boe_bf060y8m_aj0_reset(struct boe_bf060y8m_aj0 *boe)
|
||||
{
|
||||
gpiod_set_value_cansleep(boe->reset_gpio, 0);
|
||||
@ -67,12 +59,12 @@ static int boe_bf060y8m_aj0_on(struct boe_bf060y8m_aj0 *boe)
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
dsi_dcs_write_seq(dsi, 0xb0, 0xa5, 0x00);
|
||||
dsi_dcs_write_seq(dsi, 0xb2, 0x00, 0x4c);
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_SET_3D_CONTROL, 0x10);
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, DCS_ALLOW_HBM_RANGE);
|
||||
dsi_dcs_write_seq(dsi, 0xf8,
|
||||
0x00, 0x08, 0x10, 0x00, 0x22, 0x00, 0x00, 0x2d);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb0, 0xa5, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x00, 0x4c);
|
||||
mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_3D_CONTROL, 0x10);
|
||||
mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, DCS_ALLOW_HBM_RANGE);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xf8,
|
||||
0x00, 0x08, 0x10, 0x00, 0x22, 0x00, 0x00, 0x2d);
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
@ -81,17 +73,17 @@ static int boe_bf060y8m_aj0_on(struct boe_bf060y8m_aj0 *boe)
|
||||
}
|
||||
msleep(30);
|
||||
|
||||
dsi_dcs_write_seq(dsi, 0xb0, 0xa5, 0x00);
|
||||
dsi_dcs_write_seq(dsi, 0xc0,
|
||||
0x08, 0x48, 0x65, 0x33, 0x33, 0x33,
|
||||
0x2a, 0x31, 0x39, 0x20, 0x09);
|
||||
dsi_dcs_write_seq(dsi, 0xc1, 0x00, 0x00, 0x00, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f);
|
||||
dsi_dcs_write_seq(dsi, 0xe2, 0x20, 0x04, 0x10, 0x12, 0x92,
|
||||
0x4f, 0x8f, 0x44, 0x84, 0x83, 0x83, 0x83,
|
||||
0x5c, 0x5c, 0x5c);
|
||||
dsi_dcs_write_seq(dsi, 0xde, 0x01, 0x2c, 0x00, 0x77, 0x3e);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb0, 0xa5, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xc0,
|
||||
0x08, 0x48, 0x65, 0x33, 0x33, 0x33,
|
||||
0x2a, 0x31, 0x39, 0x20, 0x09);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xc1, 0x00, 0x00, 0x00, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xe2, 0x20, 0x04, 0x10, 0x12, 0x92,
|
||||
0x4f, 0x8f, 0x44, 0x84, 0x83, 0x83, 0x83,
|
||||
0x5c, 0x5c, 0x5c);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xde, 0x01, 0x2c, 0x00, 0x77, 0x3e);
|
||||
|
||||
msleep(30);
|
||||
|
||||
|
@ -1891,7 +1891,8 @@ static const struct edp_panel_entry edp_panels[] = {
|
||||
EDP_PANEL_ENTRY('C', 'M', 'N', 0x1247, &delay_200_500_e80_d50, "N120ACA-EA1"),
|
||||
|
||||
EDP_PANEL_ENTRY('I', 'V', 'O', 0x057d, &delay_200_500_e200, "R140NWF5 RH"),
|
||||
EDP_PANEL_ENTRY('I', 'V', 'O', 0x854b, &delay_200_500_p2e100, "M133NW4J-R3"),
|
||||
EDP_PANEL_ENTRY('I', 'V', 'O', 0x854a, &delay_200_500_p2e100, "M133NW4J"),
|
||||
EDP_PANEL_ENTRY('I', 'V', 'O', 0x854b, &delay_200_500_p2e100, "R133NW4K-R0"),
|
||||
|
||||
EDP_PANEL_ENTRY('K', 'D', 'B', 0x0624, &kingdisplay_kd116n21_30nv_a010.delay, "116N21-30NV-A010"),
|
||||
EDP_PANEL_ENTRY('K', 'D', 'B', 0x1120, &delay_200_500_e80_d50, "116N29-30NK-C007"),
|
||||
|
@ -51,14 +51,6 @@ static inline struct kd35t133 *panel_to_kd35t133(struct drm_panel *panel)
|
||||
return container_of(panel, struct kd35t133, panel);
|
||||
}
|
||||
|
||||
#define dsi_dcs_write_seq(dsi, cmd, seq...) do { \
|
||||
static const u8 b[] = { cmd, seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_dcs_write_buffer(dsi, b, ARRAY_SIZE(b)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
static int kd35t133_init_sequence(struct kd35t133 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
@ -68,25 +60,25 @@ static int kd35t133_init_sequence(struct kd35t133 *ctx)
|
||||
* Init sequence was supplied by the panel vendor with minimal
|
||||
* documentation.
|
||||
*/
|
||||
dsi_dcs_write_seq(dsi, KD35T133_CMD_POSITIVEGAMMA,
|
||||
0x00, 0x13, 0x18, 0x04, 0x0f, 0x06, 0x3a, 0x56,
|
||||
0x4d, 0x03, 0x0a, 0x06, 0x30, 0x3e, 0x0f);
|
||||
dsi_dcs_write_seq(dsi, KD35T133_CMD_NEGATIVEGAMMA,
|
||||
0x00, 0x13, 0x18, 0x01, 0x11, 0x06, 0x38, 0x34,
|
||||
0x4d, 0x06, 0x0d, 0x0b, 0x31, 0x37, 0x0f);
|
||||
dsi_dcs_write_seq(dsi, KD35T133_CMD_POWERCONTROL1, 0x18, 0x17);
|
||||
dsi_dcs_write_seq(dsi, KD35T133_CMD_POWERCONTROL2, 0x41);
|
||||
dsi_dcs_write_seq(dsi, KD35T133_CMD_VCOMCONTROL, 0x00, 0x1a, 0x80);
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_SET_ADDRESS_MODE, 0x48);
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PIXEL_FORMAT, 0x55);
|
||||
dsi_dcs_write_seq(dsi, KD35T133_CMD_INTERFACEMODECTRL, 0x00);
|
||||
dsi_dcs_write_seq(dsi, KD35T133_CMD_FRAMERATECTRL, 0xa0);
|
||||
dsi_dcs_write_seq(dsi, KD35T133_CMD_DISPLAYINVERSIONCTRL, 0x02);
|
||||
dsi_dcs_write_seq(dsi, KD35T133_CMD_DISPLAYFUNCTIONCTRL,
|
||||
0x20, 0x02);
|
||||
dsi_dcs_write_seq(dsi, KD35T133_CMD_SETIMAGEFUNCTION, 0x00);
|
||||
dsi_dcs_write_seq(dsi, KD35T133_CMD_ADJUSTCONTROL3,
|
||||
0xa9, 0x51, 0x2c, 0x82);
|
||||
mipi_dsi_dcs_write_seq(dsi, KD35T133_CMD_POSITIVEGAMMA,
|
||||
0x00, 0x13, 0x18, 0x04, 0x0f, 0x06, 0x3a, 0x56,
|
||||
0x4d, 0x03, 0x0a, 0x06, 0x30, 0x3e, 0x0f);
|
||||
mipi_dsi_dcs_write_seq(dsi, KD35T133_CMD_NEGATIVEGAMMA,
|
||||
0x00, 0x13, 0x18, 0x01, 0x11, 0x06, 0x38, 0x34,
|
||||
0x4d, 0x06, 0x0d, 0x0b, 0x31, 0x37, 0x0f);
|
||||
mipi_dsi_dcs_write_seq(dsi, KD35T133_CMD_POWERCONTROL1, 0x18, 0x17);
|
||||
mipi_dsi_dcs_write_seq(dsi, KD35T133_CMD_POWERCONTROL2, 0x41);
|
||||
mipi_dsi_dcs_write_seq(dsi, KD35T133_CMD_VCOMCONTROL, 0x00, 0x1a, 0x80);
|
||||
mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_ADDRESS_MODE, 0x48);
|
||||
mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PIXEL_FORMAT, 0x55);
|
||||
mipi_dsi_dcs_write_seq(dsi, KD35T133_CMD_INTERFACEMODECTRL, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, KD35T133_CMD_FRAMERATECTRL, 0xa0);
|
||||
mipi_dsi_dcs_write_seq(dsi, KD35T133_CMD_DISPLAYINVERSIONCTRL, 0x02);
|
||||
mipi_dsi_dcs_write_seq(dsi, KD35T133_CMD_DISPLAYFUNCTIONCTRL,
|
||||
0x20, 0x02);
|
||||
mipi_dsi_dcs_write_seq(dsi, KD35T133_CMD_SETIMAGEFUNCTION, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, KD35T133_CMD_ADJUSTCONTROL3,
|
||||
0xa9, 0x51, 0x2c, 0x82);
|
||||
mipi_dsi_dcs_write(dsi, MIPI_DCS_ENTER_INVERT_MODE, NULL, 0);
|
||||
|
||||
dev_dbg(dev, "Panel init sequence done\n");
|
||||
|
451
drivers/gpu/drm/panel/panel-himax-hx8394.c
Normal file
451
drivers/gpu/drm/panel/panel-himax-hx8394.c
Normal file
@ -0,0 +1,451 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Driver for panels based on Himax HX8394 controller, such as:
|
||||
*
|
||||
* - HannStar HSD060BHW4 5.99" MIPI-DSI panel
|
||||
*
|
||||
* Copyright (C) 2021 Kamil Trzciński
|
||||
*
|
||||
* Based on drivers/gpu/drm/panel/panel-sitronix-st7703.c
|
||||
* Copyright (C) Purism SPC 2019
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/media-bus-format.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
#define DRV_NAME "panel-himax-hx8394"
|
||||
|
||||
/* Manufacturer specific commands sent via DSI, listed in HX8394-F datasheet */
|
||||
#define HX8394_CMD_SETSEQUENCE 0xb0
|
||||
#define HX8394_CMD_SETPOWER 0xb1
|
||||
#define HX8394_CMD_SETDISP 0xb2
|
||||
#define HX8394_CMD_SETCYC 0xb4
|
||||
#define HX8394_CMD_SETVCOM 0xb6
|
||||
#define HX8394_CMD_SETTE 0xb7
|
||||
#define HX8394_CMD_SETSENSOR 0xb8
|
||||
#define HX8394_CMD_SETEXTC 0xb9
|
||||
#define HX8394_CMD_SETMIPI 0xba
|
||||
#define HX8394_CMD_SETOTP 0xbb
|
||||
#define HX8394_CMD_SETREGBANK 0xbd
|
||||
#define HX8394_CMD_UNKNOWN1 0xc0
|
||||
#define HX8394_CMD_SETDGCLUT 0xc1
|
||||
#define HX8394_CMD_SETID 0xc3
|
||||
#define HX8394_CMD_SETDDB 0xc4
|
||||
#define HX8394_CMD_UNKNOWN2 0xc6
|
||||
#define HX8394_CMD_SETCABC 0xc9
|
||||
#define HX8394_CMD_SETCABCGAIN 0xca
|
||||
#define HX8394_CMD_SETPANEL 0xcc
|
||||
#define HX8394_CMD_SETOFFSET 0xd2
|
||||
#define HX8394_CMD_SETGIP0 0xd3
|
||||
#define HX8394_CMD_UNKNOWN3 0xd4
|
||||
#define HX8394_CMD_SETGIP1 0xd5
|
||||
#define HX8394_CMD_SETGIP2 0xd6
|
||||
#define HX8394_CMD_SETGPO 0xd6
|
||||
#define HX8394_CMD_SETSCALING 0xdd
|
||||
#define HX8394_CMD_SETIDLE 0xdf
|
||||
#define HX8394_CMD_SETGAMMA 0xe0
|
||||
#define HX8394_CMD_SETCHEMODE_DYN 0xe4
|
||||
#define HX8394_CMD_SETCHE 0xe5
|
||||
#define HX8394_CMD_SETCESEL 0xe6
|
||||
#define HX8394_CMD_SET_SP_CMD 0xe9
|
||||
#define HX8394_CMD_SETREADINDEX 0xfe
|
||||
#define HX8394_CMD_GETSPIREAD 0xff
|
||||
|
||||
struct hx8394 {
|
||||
struct device *dev;
|
||||
struct drm_panel panel;
|
||||
struct gpio_desc *reset_gpio;
|
||||
struct regulator *vcc;
|
||||
struct regulator *iovcc;
|
||||
bool prepared;
|
||||
|
||||
const struct hx8394_panel_desc *desc;
|
||||
};
|
||||
|
||||
struct hx8394_panel_desc {
|
||||
const struct drm_display_mode *mode;
|
||||
unsigned int lanes;
|
||||
unsigned long mode_flags;
|
||||
enum mipi_dsi_pixel_format format;
|
||||
int (*init_sequence)(struct hx8394 *ctx);
|
||||
};
|
||||
|
||||
static inline struct hx8394 *panel_to_hx8394(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct hx8394, panel);
|
||||
}
|
||||
|
||||
static int hsd060bhw4_init_sequence(struct hx8394 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
|
||||
/* 5.19.8 SETEXTC: Set extension command (B9h) */
|
||||
mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETEXTC,
|
||||
0xff, 0x83, 0x94);
|
||||
|
||||
/* 5.19.2 SETPOWER: Set power (B1h) */
|
||||
mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPOWER,
|
||||
0x48, 0x11, 0x71, 0x09, 0x32, 0x24, 0x71, 0x31, 0x55, 0x30);
|
||||
|
||||
/* 5.19.9 SETMIPI: Set MIPI control (BAh) */
|
||||
mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETMIPI,
|
||||
0x63, 0x03, 0x68, 0x6b, 0xb2, 0xc0);
|
||||
|
||||
/* 5.19.3 SETDISP: Set display related register (B2h) */
|
||||
mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETDISP,
|
||||
0x00, 0x80, 0x78, 0x0c, 0x07);
|
||||
|
||||
/* 5.19.4 SETCYC: Set display waveform cycles (B4h) */
|
||||
mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETCYC,
|
||||
0x12, 0x63, 0x12, 0x63, 0x12, 0x63, 0x01, 0x0c, 0x7c, 0x55,
|
||||
0x00, 0x3f, 0x12, 0x6b, 0x12, 0x6b, 0x12, 0x6b, 0x01, 0x0c,
|
||||
0x7c);
|
||||
|
||||
/* 5.19.19 SETGIP0: Set GIP Option0 (D3h) */
|
||||
mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x3c, 0x1c, 0x00, 0x00, 0x32, 0x10,
|
||||
0x09, 0x00, 0x09, 0x32, 0x15, 0xad, 0x05, 0xad, 0x32, 0x00,
|
||||
0x00, 0x00, 0x00, 0x37, 0x03, 0x0b, 0x0b, 0x37, 0x00, 0x00,
|
||||
0x00, 0x0c, 0x40);
|
||||
|
||||
/* 5.19.20 Set GIP Option1 (D5h) */
|
||||
mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP1,
|
||||
0x19, 0x19, 0x18, 0x18, 0x1b, 0x1b, 0x1a, 0x1a, 0x00, 0x01,
|
||||
0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x20, 0x21, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x24, 0x25, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18);
|
||||
|
||||
/* 5.19.21 Set GIP Option2 (D6h) */
|
||||
mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP2,
|
||||
0x18, 0x18, 0x19, 0x19, 0x1b, 0x1b, 0x1a, 0x1a, 0x07, 0x06,
|
||||
0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x25, 0x24, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18);
|
||||
|
||||
/* 5.19.25 SETGAMMA: Set gamma curve related setting (E0h) */
|
||||
mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGAMMA,
|
||||
0x00, 0x04, 0x0c, 0x12, 0x14, 0x18, 0x1a, 0x18, 0x31, 0x3f,
|
||||
0x4d, 0x4c, 0x54, 0x65, 0x6b, 0x70, 0x7f, 0x82, 0x7e, 0x8a,
|
||||
0x99, 0x4a, 0x48, 0x49, 0x4b, 0x4a, 0x4c, 0x4b, 0x7f, 0x00,
|
||||
0x04, 0x0c, 0x11, 0x13, 0x17, 0x1a, 0x18, 0x31,
|
||||
0x3f, 0x4d, 0x4c, 0x54, 0x65, 0x6b, 0x70, 0x7f,
|
||||
0x82, 0x7e, 0x8a, 0x99, 0x4a, 0x48, 0x49, 0x4b,
|
||||
0x4a, 0x4c, 0x4b, 0x7f);
|
||||
|
||||
/* 5.19.17 SETPANEL (CCh) */
|
||||
mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPANEL,
|
||||
0x0b);
|
||||
|
||||
/* Unknown command, not listed in the HX8394-F datasheet */
|
||||
mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN1,
|
||||
0x1f, 0x31);
|
||||
|
||||
/* 5.19.5 SETVCOM: Set VCOM voltage (B6h) */
|
||||
mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETVCOM,
|
||||
0x7d, 0x7d);
|
||||
|
||||
/* Unknown command, not listed in the HX8394-F datasheet */
|
||||
mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN3,
|
||||
0x02);
|
||||
|
||||
/* 5.19.11 Set register bank (BDh) */
|
||||
mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK,
|
||||
0x01);
|
||||
|
||||
/* 5.19.2 SETPOWER: Set power (B1h) */
|
||||
mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPOWER,
|
||||
0x00);
|
||||
|
||||
/* 5.19.11 Set register bank (BDh) */
|
||||
mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK,
|
||||
0x00);
|
||||
|
||||
/* Unknown command, not listed in the HX8394-F datasheet */
|
||||
mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN3,
|
||||
0xed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode hsd060bhw4_mode = {
|
||||
.hdisplay = 720,
|
||||
.hsync_start = 720 + 40,
|
||||
.hsync_end = 720 + 40 + 46,
|
||||
.htotal = 720 + 40 + 46 + 40,
|
||||
.vdisplay = 1440,
|
||||
.vsync_start = 1440 + 9,
|
||||
.vsync_end = 1440 + 9 + 7,
|
||||
.vtotal = 1440 + 9 + 7 + 7,
|
||||
.clock = 74250,
|
||||
.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
|
||||
.width_mm = 68,
|
||||
.height_mm = 136,
|
||||
};
|
||||
|
||||
static const struct hx8394_panel_desc hsd060bhw4_desc = {
|
||||
.mode = &hsd060bhw4_mode,
|
||||
.lanes = 4,
|
||||
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST,
|
||||
.format = MIPI_DSI_FMT_RGB888,
|
||||
.init_sequence = hsd060bhw4_init_sequence,
|
||||
};
|
||||
|
||||
static int hx8394_enable(struct drm_panel *panel)
|
||||
{
|
||||
struct hx8394 *ctx = panel_to_hx8394(panel);
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
int ret;
|
||||
|
||||
ret = ctx->desc->init_sequence(ctx);
|
||||
if (ret) {
|
||||
dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
|
||||
if (ret) {
|
||||
dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Panel is operational 120 msec after reset */
|
||||
msleep(120);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(dsi);
|
||||
if (ret) {
|
||||
dev_err(ctx->dev, "Failed to turn on the display: %d\n", ret);
|
||||
goto sleep_in;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
sleep_in:
|
||||
/* This will probably fail, but let's try orderly power off anyway. */
|
||||
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||
if (!ret)
|
||||
msleep(50);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hx8394_disable(struct drm_panel *panel)
|
||||
{
|
||||
struct hx8394 *ctx = panel_to_hx8394(panel);
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||
if (ret) {
|
||||
dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
msleep(50); /* about 3 frames */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hx8394_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct hx8394 *ctx = panel_to_hx8394(panel);
|
||||
|
||||
if (!ctx->prepared)
|
||||
return 0;
|
||||
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
|
||||
regulator_disable(ctx->iovcc);
|
||||
regulator_disable(ctx->vcc);
|
||||
|
||||
ctx->prepared = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hx8394_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct hx8394 *ctx = panel_to_hx8394(panel);
|
||||
int ret;
|
||||
|
||||
if (ctx->prepared)
|
||||
return 0;
|
||||
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
|
||||
ret = regulator_enable(ctx->vcc);
|
||||
if (ret) {
|
||||
dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regulator_enable(ctx->iovcc);
|
||||
if (ret) {
|
||||
dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret);
|
||||
goto disable_vcc;
|
||||
}
|
||||
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
|
||||
msleep(180);
|
||||
|
||||
ctx->prepared = true;
|
||||
|
||||
return 0;
|
||||
|
||||
disable_vcc:
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
regulator_disable(ctx->vcc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hx8394_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct hx8394 *ctx = panel_to_hx8394(panel);
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev, ctx->desc->mode);
|
||||
if (!mode) {
|
||||
dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n",
|
||||
ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
|
||||
drm_mode_vrefresh(ctx->desc->mode));
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
|
||||
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
||||
connector->display_info.width_mm = mode->width_mm;
|
||||
connector->display_info.height_mm = mode->height_mm;
|
||||
drm_mode_probed_add(connector, mode);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs hx8394_drm_funcs = {
|
||||
.disable = hx8394_disable,
|
||||
.unprepare = hx8394_unprepare,
|
||||
.prepare = hx8394_prepare,
|
||||
.enable = hx8394_enable,
|
||||
.get_modes = hx8394_get_modes,
|
||||
};
|
||||
|
||||
static int hx8394_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
struct hx8394 *ctx;
|
||||
int ret;
|
||||
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(ctx->reset_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
|
||||
"Failed to get reset gpio\n");
|
||||
|
||||
mipi_dsi_set_drvdata(dsi, ctx);
|
||||
|
||||
ctx->dev = dev;
|
||||
ctx->desc = of_device_get_match_data(dev);
|
||||
|
||||
dsi->mode_flags = ctx->desc->mode_flags;
|
||||
dsi->format = ctx->desc->format;
|
||||
dsi->lanes = ctx->desc->lanes;
|
||||
|
||||
ctx->vcc = devm_regulator_get(dev, "vcc");
|
||||
if (IS_ERR(ctx->vcc))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->vcc),
|
||||
"Failed to request vcc regulator\n");
|
||||
|
||||
ctx->iovcc = devm_regulator_get(dev, "iovcc");
|
||||
if (IS_ERR(ctx->iovcc))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->iovcc),
|
||||
"Failed to request iovcc regulator\n");
|
||||
|
||||
drm_panel_init(&ctx->panel, dev, &hx8394_drm_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
ret = drm_panel_of_backlight(&ctx->panel);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_panel_add(&ctx->panel);
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err_probe(dev, ret, "mipi_dsi_attach failed\n");
|
||||
drm_panel_remove(&ctx->panel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "%ux%u@%u %ubpp dsi %udl - ready\n",
|
||||
ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
|
||||
drm_mode_vrefresh(ctx->desc->mode),
|
||||
mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hx8394_shutdown(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct hx8394 *ctx = mipi_dsi_get_drvdata(dsi);
|
||||
int ret;
|
||||
|
||||
ret = drm_panel_disable(&ctx->panel);
|
||||
if (ret < 0)
|
||||
dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
|
||||
|
||||
ret = drm_panel_unprepare(&ctx->panel);
|
||||
if (ret < 0)
|
||||
dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);
|
||||
}
|
||||
|
||||
static void hx8394_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct hx8394 *ctx = mipi_dsi_get_drvdata(dsi);
|
||||
int ret;
|
||||
|
||||
hx8394_shutdown(dsi);
|
||||
|
||||
ret = mipi_dsi_detach(dsi);
|
||||
if (ret < 0)
|
||||
dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
|
||||
|
||||
drm_panel_remove(&ctx->panel);
|
||||
}
|
||||
|
||||
static const struct of_device_id hx8394_of_match[] = {
|
||||
{ .compatible = "hannstar,hsd060bhw4", .data = &hsd060bhw4_desc },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, hx8394_of_match);
|
||||
|
||||
static struct mipi_dsi_driver hx8394_driver = {
|
||||
.probe = hx8394_probe,
|
||||
.remove = hx8394_remove,
|
||||
.shutdown = hx8394_shutdown,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = hx8394_of_match,
|
||||
},
|
||||
};
|
||||
module_mipi_dsi_driver(hx8394_driver);
|
||||
|
||||
MODULE_AUTHOR("Kamil Trzciński <ayufan@ayufan.eu>");
|
||||
MODULE_DESCRIPTION("DRM driver for Himax HX8394 based MIPI DSI panels");
|
||||
MODULE_LICENSE("GPL");
|
@ -29,22 +29,6 @@ static inline struct jdi_fhd_r63452 *to_jdi_fhd_r63452(struct drm_panel *panel)
|
||||
return container_of(panel, struct jdi_fhd_r63452, panel);
|
||||
}
|
||||
|
||||
#define dsi_generic_write_seq(dsi, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
#define dsi_dcs_write_seq(dsi, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
static void jdi_fhd_r63452_reset(struct jdi_fhd_r63452 *ctx)
|
||||
{
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
@ -63,12 +47,12 @@ static int jdi_fhd_r63452_on(struct jdi_fhd_r63452 *ctx)
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
dsi_generic_write_seq(dsi, 0xb0, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xd6, 0x01);
|
||||
dsi_generic_write_seq(dsi, 0xec,
|
||||
0x64, 0xdc, 0xec, 0x3b, 0x52, 0x00, 0x0b, 0x0b,
|
||||
0x13, 0x15, 0x68, 0x0b, 0xb5);
|
||||
dsi_generic_write_seq(dsi, 0xb0, 0x03);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb0, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd6, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xec,
|
||||
0x64, 0xdc, 0xec, 0x3b, 0x52, 0x00, 0x0b, 0x0b,
|
||||
0x13, 0x15, 0x68, 0x0b, 0xb5);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb0, 0x03);
|
||||
|
||||
ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
|
||||
if (ret < 0) {
|
||||
@ -76,7 +60,7 @@ static int jdi_fhd_r63452_on(struct jdi_fhd_r63452 *ctx)
|
||||
return ret;
|
||||
}
|
||||
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
|
||||
|
||||
ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x77);
|
||||
if (ret < 0) {
|
||||
@ -108,10 +92,10 @@ static int jdi_fhd_r63452_on(struct jdi_fhd_r63452 *ctx)
|
||||
return ret;
|
||||
}
|
||||
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24);
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS, 0x00);
|
||||
dsi_dcs_write_seq(dsi, 0x84, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24);
|
||||
mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0x84, 0x00);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(dsi);
|
||||
if (ret < 0) {
|
||||
@ -127,10 +111,10 @@ static int jdi_fhd_r63452_on(struct jdi_fhd_r63452 *ctx)
|
||||
}
|
||||
msleep(80);
|
||||
|
||||
dsi_generic_write_seq(dsi, 0xb0, 0x04);
|
||||
dsi_dcs_write_seq(dsi, 0x84, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xc8, 0x11);
|
||||
dsi_generic_write_seq(dsi, 0xb0, 0x03);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb0, 0x04);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0x84, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc8, 0x11);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb0, 0x03);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -143,12 +127,12 @@ static int jdi_fhd_r63452_off(struct jdi_fhd_r63452 *ctx)
|
||||
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
dsi_generic_write_seq(dsi, 0xb0, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xd6, 0x01);
|
||||
dsi_generic_write_seq(dsi, 0xec,
|
||||
0x64, 0xdc, 0xec, 0x3b, 0x52, 0x00, 0x0b, 0x0b,
|
||||
0x13, 0x15, 0x68, 0x0b, 0x95);
|
||||
dsi_generic_write_seq(dsi, 0xb0, 0x03);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb0, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd6, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xec,
|
||||
0x64, 0xdc, 0xec, 0x3b, 0x52, 0x00, 0x0b, 0x0b,
|
||||
0x13, 0x15, 0x68, 0x0b, 0x95);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb0, 0x03);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_off(dsi);
|
||||
if (ret < 0) {
|
||||
|
@ -244,14 +244,6 @@ struct ltk050h3146w *panel_to_ltk050h3146w(struct drm_panel *panel)
|
||||
return container_of(panel, struct ltk050h3146w, panel);
|
||||
}
|
||||
|
||||
#define dsi_dcs_write_seq(dsi, cmd, seq...) do { \
|
||||
static const u8 b[] = { cmd, seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_dcs_write_buffer(dsi, b, ARRAY_SIZE(b)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
static int ltk050h3146w_init_sequence(struct ltk050h3146w *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
@ -261,55 +253,55 @@ static int ltk050h3146w_init_sequence(struct ltk050h3146w *ctx)
|
||||
* Init sequence was supplied by the panel vendor without much
|
||||
* documentation.
|
||||
*/
|
||||
dsi_dcs_write_seq(dsi, 0xdf, 0x93, 0x65, 0xf8);
|
||||
dsi_dcs_write_seq(dsi, 0xb0, 0x01, 0x03, 0x02, 0x00, 0x64, 0x06,
|
||||
0x01);
|
||||
dsi_dcs_write_seq(dsi, 0xb2, 0x00, 0xb5);
|
||||
dsi_dcs_write_seq(dsi, 0xb3, 0x00, 0xb5);
|
||||
dsi_dcs_write_seq(dsi, 0xb7, 0x00, 0xbf, 0x00, 0x00, 0xbf, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xdf, 0x93, 0x65, 0xf8);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x01, 0x03, 0x02, 0x00, 0x64, 0x06,
|
||||
0x01);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x00, 0xb5);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x00, 0xb5);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x00, 0xbf, 0x00, 0x00, 0xbf, 0x00);
|
||||
|
||||
dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0xc4, 0x23, 0x07);
|
||||
dsi_dcs_write_seq(dsi, 0xbb, 0x02, 0x01, 0x24, 0x00, 0x28, 0x0f,
|
||||
0x28, 0x04, 0xcc, 0xcc, 0xcc);
|
||||
dsi_dcs_write_seq(dsi, 0xbc, 0x0f, 0x04);
|
||||
dsi_dcs_write_seq(dsi, 0xbe, 0x1e, 0xf2);
|
||||
dsi_dcs_write_seq(dsi, 0xc0, 0x26, 0x03);
|
||||
dsi_dcs_write_seq(dsi, 0xc1, 0x00, 0x12);
|
||||
dsi_dcs_write_seq(dsi, 0xc3, 0x04, 0x02, 0x02, 0x76, 0x01, 0x80,
|
||||
0x80);
|
||||
dsi_dcs_write_seq(dsi, 0xc4, 0x24, 0x80, 0xb4, 0x81, 0x12, 0x0f,
|
||||
0x16, 0x00, 0x00);
|
||||
dsi_dcs_write_seq(dsi, 0xc8, 0x7f, 0x72, 0x67, 0x5d, 0x5d, 0x50,
|
||||
0x56, 0x41, 0x59, 0x57, 0x55, 0x70, 0x5b, 0x5f,
|
||||
0x4f, 0x47, 0x38, 0x23, 0x08, 0x7f, 0x72, 0x67,
|
||||
0x5d, 0x5d, 0x50, 0x56, 0x41, 0x59, 0x57, 0x55,
|
||||
0x70, 0x5b, 0x5f, 0x4f, 0x47, 0x38, 0x23, 0x08);
|
||||
dsi_dcs_write_seq(dsi, 0xd0, 0x1e, 0x1f, 0x57, 0x58, 0x48, 0x4a,
|
||||
0x44, 0x46, 0x40, 0x1f, 0x42, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f);
|
||||
dsi_dcs_write_seq(dsi, 0xd1, 0x1e, 0x1f, 0x57, 0x58, 0x49, 0x4b,
|
||||
0x45, 0x47, 0x41, 0x1f, 0x43, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f);
|
||||
dsi_dcs_write_seq(dsi, 0xd2, 0x1f, 0x1e, 0x17, 0x18, 0x07, 0x05,
|
||||
0x0b, 0x09, 0x03, 0x1f, 0x01, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f);
|
||||
dsi_dcs_write_seq(dsi, 0xd3, 0x1f, 0x1e, 0x17, 0x18, 0x06, 0x04,
|
||||
0x0a, 0x08, 0x02, 0x1f, 0x00, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f);
|
||||
dsi_dcs_write_seq(dsi, 0xd4, 0x00, 0x00, 0x00, 0x0c, 0x06, 0x20,
|
||||
0x01, 0x02, 0x00, 0x60, 0x15, 0xb0, 0x30, 0x03,
|
||||
0x04, 0x00, 0x60, 0x72, 0x0a, 0x00, 0x60, 0x08);
|
||||
dsi_dcs_write_seq(dsi, 0xd5, 0x00, 0x06, 0x06, 0x00, 0x30, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xbc, 0x50, 0x00, 0x05,
|
||||
0x21, 0x00, 0x60);
|
||||
dsi_dcs_write_seq(dsi, 0xdd, 0x2c, 0xa3, 0x00);
|
||||
dsi_dcs_write_seq(dsi, 0xde, 0x02);
|
||||
dsi_dcs_write_seq(dsi, 0xb2, 0x32, 0x1c);
|
||||
dsi_dcs_write_seq(dsi, 0xb7, 0x3b, 0x70, 0x00, 0x04);
|
||||
dsi_dcs_write_seq(dsi, 0xc1, 0x11);
|
||||
dsi_dcs_write_seq(dsi, 0xbb, 0x21, 0x22, 0x23, 0x24, 0x36, 0x37);
|
||||
dsi_dcs_write_seq(dsi, 0xc2, 0x20, 0x38, 0x1e, 0x84);
|
||||
dsi_dcs_write_seq(dsi, 0xde, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0xc4, 0x23, 0x07);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x02, 0x01, 0x24, 0x00, 0x28, 0x0f,
|
||||
0x28, 0x04, 0xcc, 0xcc, 0xcc);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xbc, 0x0f, 0x04);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xbe, 0x1e, 0xf2);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xc0, 0x26, 0x03);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xc1, 0x00, 0x12);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xc3, 0x04, 0x02, 0x02, 0x76, 0x01, 0x80,
|
||||
0x80);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xc4, 0x24, 0x80, 0xb4, 0x81, 0x12, 0x0f,
|
||||
0x16, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xc8, 0x7f, 0x72, 0x67, 0x5d, 0x5d, 0x50,
|
||||
0x56, 0x41, 0x59, 0x57, 0x55, 0x70, 0x5b, 0x5f,
|
||||
0x4f, 0x47, 0x38, 0x23, 0x08, 0x7f, 0x72, 0x67,
|
||||
0x5d, 0x5d, 0x50, 0x56, 0x41, 0x59, 0x57, 0x55,
|
||||
0x70, 0x5b, 0x5f, 0x4f, 0x47, 0x38, 0x23, 0x08);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xd0, 0x1e, 0x1f, 0x57, 0x58, 0x48, 0x4a,
|
||||
0x44, 0x46, 0x40, 0x1f, 0x42, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xd1, 0x1e, 0x1f, 0x57, 0x58, 0x49, 0x4b,
|
||||
0x45, 0x47, 0x41, 0x1f, 0x43, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xd2, 0x1f, 0x1e, 0x17, 0x18, 0x07, 0x05,
|
||||
0x0b, 0x09, 0x03, 0x1f, 0x01, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xd3, 0x1f, 0x1e, 0x17, 0x18, 0x06, 0x04,
|
||||
0x0a, 0x08, 0x02, 0x1f, 0x00, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xd4, 0x00, 0x00, 0x00, 0x0c, 0x06, 0x20,
|
||||
0x01, 0x02, 0x00, 0x60, 0x15, 0xb0, 0x30, 0x03,
|
||||
0x04, 0x00, 0x60, 0x72, 0x0a, 0x00, 0x60, 0x08);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xd5, 0x00, 0x06, 0x06, 0x00, 0x30, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xbc, 0x50, 0x00, 0x05,
|
||||
0x21, 0x00, 0x60);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xdd, 0x2c, 0xa3, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xde, 0x02);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x32, 0x1c);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x3b, 0x70, 0x00, 0x04);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xc1, 0x11);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x21, 0x22, 0x23, 0x24, 0x36, 0x37);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xc2, 0x20, 0x38, 0x1e, 0x84);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xde, 0x00);
|
||||
|
||||
ret = mipi_dsi_dcs_set_tear_on(dsi, 1);
|
||||
if (ret < 0) {
|
||||
|
@ -45,14 +45,6 @@ static inline struct mantix *panel_to_mantix(struct drm_panel *panel)
|
||||
return container_of(panel, struct mantix, panel);
|
||||
}
|
||||
|
||||
#define dsi_generic_write_seq(dsi, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
static int mantix_init_sequence(struct mantix *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
@ -61,18 +53,18 @@ static int mantix_init_sequence(struct mantix *ctx)
|
||||
/*
|
||||
* Init sequence was supplied by the panel vendor.
|
||||
*/
|
||||
dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5A);
|
||||
mipi_dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5A);
|
||||
|
||||
dsi_generic_write_seq(dsi, MANTIX_CMD_INT_CANCEL, 0x03);
|
||||
dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5A, 0x03);
|
||||
dsi_generic_write_seq(dsi, 0x80, 0xA9, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, MANTIX_CMD_INT_CANCEL, 0x03);
|
||||
mipi_dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5A, 0x03);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x80, 0xA9, 0x00);
|
||||
|
||||
dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5A, 0x09);
|
||||
dsi_generic_write_seq(dsi, 0x80, 0x64, 0x00, 0x64, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5A, 0x09);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x80, 0x64, 0x00, 0x64, 0x00, 0x00);
|
||||
msleep(20);
|
||||
|
||||
dsi_generic_write_seq(dsi, MANTIX_CMD_SPI_FINISH, 0xA5);
|
||||
dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x00, 0x2F);
|
||||
mipi_dsi_generic_write_seq(dsi, MANTIX_CMD_SPI_FINISH, 0xA5);
|
||||
mipi_dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x00, 0x2F);
|
||||
msleep(20);
|
||||
|
||||
dev_dbg(dev, "Panel init sequence done\n");
|
||||
|
@ -89,14 +89,6 @@ static inline struct nt35950 *to_nt35950(struct drm_panel *panel)
|
||||
return container_of(panel, struct nt35950, panel);
|
||||
}
|
||||
|
||||
#define dsi_dcs_write_seq(dsi, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
static void nt35950_reset(struct nt35950 *nt)
|
||||
{
|
||||
gpiod_set_value_cansleep(nt->reset_gpio, 1);
|
||||
@ -338,7 +330,7 @@ static int nt35950_on(struct nt35950 *nt)
|
||||
return ret;
|
||||
|
||||
/* Unknown command */
|
||||
dsi_dcs_write_seq(dsi, 0xd4, 0x88, 0x88);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xd4, 0x88, 0x88);
|
||||
|
||||
/* CMD2 Page 7 */
|
||||
ret = nt35950_set_cmd2_page(nt, 7);
|
||||
@ -346,10 +338,10 @@ static int nt35950_on(struct nt35950 *nt)
|
||||
return ret;
|
||||
|
||||
/* Enable SubPixel Rendering */
|
||||
dsi_dcs_write_seq(dsi, MCS_PARAM_SPR_EN, 0x01);
|
||||
mipi_dsi_dcs_write_seq(dsi, MCS_PARAM_SPR_EN, 0x01);
|
||||
|
||||
/* SPR Mode: YYG Rainbow-RGB */
|
||||
dsi_dcs_write_seq(dsi, MCS_PARAM_SPR_MODE, MCS_SPR_MODE_YYG_RAINBOW_RGB);
|
||||
mipi_dsi_dcs_write_seq(dsi, MCS_PARAM_SPR_MODE, MCS_SPR_MODE_YYG_RAINBOW_RGB);
|
||||
|
||||
/* CMD3 */
|
||||
ret = nt35950_inject_black_image(nt);
|
||||
|
@ -202,8 +202,7 @@ static const struct drm_panel_funcs lcd_olinuxino_funcs = {
|
||||
.get_modes = lcd_olinuxino_get_modes,
|
||||
};
|
||||
|
||||
static int lcd_olinuxino_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int lcd_olinuxino_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct lcd_olinuxino *lcd;
|
||||
@ -309,7 +308,7 @@ static struct i2c_driver lcd_olinuxino_driver = {
|
||||
.name = "lcd_olinuxino",
|
||||
.of_match_table = lcd_olinuxino_of_ids,
|
||||
},
|
||||
.probe = lcd_olinuxino_probe,
|
||||
.probe_new = lcd_olinuxino_probe,
|
||||
.remove = lcd_olinuxino_remove,
|
||||
};
|
||||
|
||||
|
@ -362,8 +362,7 @@ static const struct drm_panel_funcs rpi_touchscreen_funcs = {
|
||||
.get_modes = rpi_touchscreen_get_modes,
|
||||
};
|
||||
|
||||
static int rpi_touchscreen_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
static int rpi_touchscreen_probe(struct i2c_client *i2c)
|
||||
{
|
||||
struct device *dev = &i2c->dev;
|
||||
struct rpi_touchscreen *ts;
|
||||
@ -491,7 +490,7 @@ static struct i2c_driver rpi_touchscreen_driver = {
|
||||
.name = "rpi_touchscreen",
|
||||
.of_match_table = rpi_touchscreen_of_ids,
|
||||
},
|
||||
.probe = rpi_touchscreen_probe,
|
||||
.probe_new = rpi_touchscreen_probe,
|
||||
.remove = rpi_touchscreen_remove,
|
||||
};
|
||||
|
||||
|
@ -28,14 +28,6 @@ s6e88a0_ams452ef01 *to_s6e88a0_ams452ef01(struct drm_panel *panel)
|
||||
return container_of(panel, struct s6e88a0_ams452ef01, panel);
|
||||
}
|
||||
|
||||
#define dsi_dcs_write_seq(dsi, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
static void s6e88a0_ams452ef01_reset(struct s6e88a0_ams452ef01 *ctx)
|
||||
{
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
@ -54,8 +46,8 @@ static int s6e88a0_ams452ef01_on(struct s6e88a0_ams452ef01 *ctx)
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a); // enable LEVEL2 commands
|
||||
dsi_dcs_write_seq(dsi, 0xcc, 0x4c); // set Pixel Clock Divider polarity
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a); // enable LEVEL2 commands
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xcc, 0x4c); // set Pixel Clock Divider polarity
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
@ -65,23 +57,23 @@ static int s6e88a0_ams452ef01_on(struct s6e88a0_ams452ef01 *ctx)
|
||||
msleep(120);
|
||||
|
||||
// set default brightness/gama
|
||||
dsi_dcs_write_seq(dsi, 0xca,
|
||||
0x01, 0x00, 0x01, 0x00, 0x01, 0x00, // V255 RR,GG,BB
|
||||
0x80, 0x80, 0x80, // V203 R,G,B
|
||||
0x80, 0x80, 0x80, // V151 R,G,B
|
||||
0x80, 0x80, 0x80, // V87 R,G,B
|
||||
0x80, 0x80, 0x80, // V51 R,G,B
|
||||
0x80, 0x80, 0x80, // V35 R,G,B
|
||||
0x80, 0x80, 0x80, // V23 R,G,B
|
||||
0x80, 0x80, 0x80, // V11 R,G,B
|
||||
0x6b, 0x68, 0x71, // V3 R,G,B
|
||||
0x00, 0x00, 0x00); // V1 R,G,B
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xca,
|
||||
0x01, 0x00, 0x01, 0x00, 0x01, 0x00, // V255 RR,GG,BB
|
||||
0x80, 0x80, 0x80, // V203 R,G,B
|
||||
0x80, 0x80, 0x80, // V151 R,G,B
|
||||
0x80, 0x80, 0x80, // V87 R,G,B
|
||||
0x80, 0x80, 0x80, // V51 R,G,B
|
||||
0x80, 0x80, 0x80, // V35 R,G,B
|
||||
0x80, 0x80, 0x80, // V23 R,G,B
|
||||
0x80, 0x80, 0x80, // V11 R,G,B
|
||||
0x6b, 0x68, 0x71, // V3 R,G,B
|
||||
0x00, 0x00, 0x00); // V1 R,G,B
|
||||
// set default Amoled Off Ratio
|
||||
dsi_dcs_write_seq(dsi, 0xb2, 0x40, 0x0a, 0x17, 0x00, 0x0a);
|
||||
dsi_dcs_write_seq(dsi, 0xb6, 0x2c, 0x0b); // set default elvss voltage
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
|
||||
dsi_dcs_write_seq(dsi, 0xf7, 0x03); // gamma/aor update
|
||||
dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5); // disable LEVEL2 commands
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x40, 0x0a, 0x17, 0x00, 0x0a);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x2c, 0x0b); // set default elvss voltage
|
||||
mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xf7, 0x03); // gamma/aor update
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5); // disable LEVEL2 commands
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(dsi);
|
||||
if (ret < 0) {
|
||||
|
@ -34,14 +34,6 @@ struct sofef00_panel *to_sofef00_panel(struct drm_panel *panel)
|
||||
return container_of(panel, struct sofef00_panel, panel);
|
||||
}
|
||||
|
||||
#define dsi_dcs_write_seq(dsi, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
static void sofef00_panel_reset(struct sofef00_panel *ctx)
|
||||
{
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
@ -67,7 +59,7 @@ static int sofef00_panel_on(struct sofef00_panel *ctx)
|
||||
}
|
||||
usleep_range(10000, 11000);
|
||||
|
||||
dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
|
||||
|
||||
ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
|
||||
if (ret < 0) {
|
||||
@ -75,13 +67,13 @@ static int sofef00_panel_on(struct sofef00_panel *ctx)
|
||||
return ret;
|
||||
}
|
||||
|
||||
dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
|
||||
dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
|
||||
dsi_dcs_write_seq(dsi, 0xb0, 0x07);
|
||||
dsi_dcs_write_seq(dsi, 0xb6, 0x12);
|
||||
dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x20);
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x07);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x12);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
|
||||
mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x20);
|
||||
mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(dsi);
|
||||
if (ret < 0) {
|
||||
|
@ -32,12 +32,6 @@ static inline struct sharp_ls060 *to_sharp_ls060(struct drm_panel *panel)
|
||||
return container_of(panel, struct sharp_ls060, panel);
|
||||
}
|
||||
|
||||
#define dsi_dcs_write_seq(dsi, seq...) ({ \
|
||||
static const u8 d[] = { seq }; \
|
||||
\
|
||||
mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
|
||||
})
|
||||
|
||||
static void sharp_ls060_reset(struct sharp_ls060 *ctx)
|
||||
{
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
@ -56,17 +50,8 @@ static int sharp_ls060_on(struct sharp_ls060 *ctx)
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = dsi_dcs_write_seq(dsi, 0xbb, 0x13);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to send command: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_MEMORY_START);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to send command: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x13);
|
||||
mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_MEMORY_START);
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
|
@ -73,14 +73,6 @@ static inline struct st7703 *panel_to_st7703(struct drm_panel *panel)
|
||||
return container_of(panel, struct st7703, panel);
|
||||
}
|
||||
|
||||
#define dsi_generic_write_seq(dsi, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
static int jh057n_init_sequence(struct st7703 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
@ -90,50 +82,50 @@ static int jh057n_init_sequence(struct st7703 *ctx)
|
||||
* resemble the ST7703 but the number of parameters often don't match
|
||||
* so it's likely a clone.
|
||||
*/
|
||||
dsi_generic_write_seq(dsi, ST7703_CMD_SETEXTC,
|
||||
0xF1, 0x12, 0x83);
|
||||
dsi_generic_write_seq(dsi, ST7703_CMD_SETRGBIF,
|
||||
0x10, 0x10, 0x05, 0x05, 0x03, 0xFF, 0x00, 0x00,
|
||||
0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, ST7703_CMD_SETSCR,
|
||||
0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70,
|
||||
0x00);
|
||||
dsi_generic_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E);
|
||||
dsi_generic_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B);
|
||||
dsi_generic_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
|
||||
dsi_generic_write_seq(dsi, ST7703_CMD_SETDISP, 0xF0, 0x12, 0x30);
|
||||
dsi_generic_write_seq(dsi, ST7703_CMD_SETEQ,
|
||||
0x07, 0x07, 0x0B, 0x0B, 0x03, 0x0B, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFF, 0x00, 0xC0, 0x10);
|
||||
dsi_generic_write_seq(dsi, ST7703_CMD_SETBGP, 0x08, 0x08);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETEXTC,
|
||||
0xF1, 0x12, 0x83);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETRGBIF,
|
||||
0x10, 0x10, 0x05, 0x05, 0x03, 0xFF, 0x00, 0x00,
|
||||
0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETSCR,
|
||||
0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70,
|
||||
0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETDISP, 0xF0, 0x12, 0x30);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETEQ,
|
||||
0x07, 0x07, 0x0B, 0x0B, 0x03, 0x0B, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFF, 0x00, 0xC0, 0x10);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETBGP, 0x08, 0x08);
|
||||
msleep(20);
|
||||
|
||||
dsi_generic_write_seq(dsi, ST7703_CMD_SETVCOM, 0x3F, 0x3F);
|
||||
dsi_generic_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
|
||||
dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP1,
|
||||
0x82, 0x10, 0x06, 0x05, 0x9E, 0x0A, 0xA5, 0x12,
|
||||
0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
|
||||
0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64,
|
||||
0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP2,
|
||||
0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13,
|
||||
0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0A,
|
||||
0xA5, 0x00, 0x00, 0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, ST7703_CMD_SETGAMMA,
|
||||
0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41, 0x37,
|
||||
0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10, 0x11,
|
||||
0x18, 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41,
|
||||
0x37, 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10,
|
||||
0x11, 0x18);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETVCOM, 0x3F, 0x3F);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP1,
|
||||
0x82, 0x10, 0x06, 0x05, 0x9E, 0x0A, 0xA5, 0x12,
|
||||
0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
|
||||
0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64,
|
||||
0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP2,
|
||||
0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13,
|
||||
0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0A,
|
||||
0xA5, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETGAMMA,
|
||||
0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41, 0x37,
|
||||
0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10, 0x11,
|
||||
0x18, 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41,
|
||||
0x37, 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10,
|
||||
0x11, 0x18);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -162,15 +154,6 @@ static const struct st7703_panel_desc jh057n00900_panel_desc = {
|
||||
.init_sequence = jh057n_init_sequence,
|
||||
};
|
||||
|
||||
#define dsi_dcs_write_seq(dsi, cmd, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_dcs_write(dsi, cmd, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
|
||||
static int xbd599_init_sequence(struct st7703 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
@ -180,154 +163,154 @@ static int xbd599_init_sequence(struct st7703 *ctx)
|
||||
*/
|
||||
|
||||
/* Magic sequence to unlock user commands below. */
|
||||
dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xF1, 0x12, 0x83);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xF1, 0x12, 0x83);
|
||||
|
||||
dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI,
|
||||
0x33, /* VC_main = 0, Lane_Number = 3 (4 lanes) */
|
||||
0x81, /* DSI_LDO_SEL = 1.7V, RTERM = 90 Ohm */
|
||||
0x05, /* IHSRX = x6 (Low High Speed driving ability) */
|
||||
0xF9, /* TX_CLK_SEL = fDSICLK/16 */
|
||||
0x0E, /* HFP_OSC (min. HFP number in DSI mode) */
|
||||
0x0E, /* HBP_OSC (min. HBP number in DSI mode) */
|
||||
/* The rest is undocumented in ST7703 datasheet */
|
||||
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x44, 0x25, 0x00, 0x91, 0x0a, 0x00, 0x00, 0x02,
|
||||
0x4F, 0x11, 0x00, 0x00, 0x37);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI,
|
||||
0x33, /* VC_main = 0, Lane_Number = 3 (4 lanes) */
|
||||
0x81, /* DSI_LDO_SEL = 1.7V, RTERM = 90 Ohm */
|
||||
0x05, /* IHSRX = x6 (Low High Speed driving ability) */
|
||||
0xF9, /* TX_CLK_SEL = fDSICLK/16 */
|
||||
0x0E, /* HFP_OSC (min. HFP number in DSI mode) */
|
||||
0x0E, /* HBP_OSC (min. HBP number in DSI mode) */
|
||||
/* The rest is undocumented in ST7703 datasheet */
|
||||
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x44, 0x25, 0x00, 0x91, 0x0a, 0x00, 0x00, 0x02,
|
||||
0x4F, 0x11, 0x00, 0x00, 0x37);
|
||||
|
||||
dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT,
|
||||
0x25, /* PCCS = 2, ECP_DC_DIV = 1/4 HSYNC */
|
||||
0x22, /* DT = 15ms XDK_ECP = x2 */
|
||||
0x20, /* PFM_DC_DIV = /1 */
|
||||
0x03 /* ECP_SYNC_EN = 1, VGX_SYNC_EN = 1 */);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT,
|
||||
0x25, /* PCCS = 2, ECP_DC_DIV = 1/4 HSYNC */
|
||||
0x22, /* DT = 15ms XDK_ECP = x2 */
|
||||
0x20, /* PFM_DC_DIV = /1 */
|
||||
0x03 /* ECP_SYNC_EN = 1, VGX_SYNC_EN = 1 */);
|
||||
|
||||
/* RGB I/F porch timing */
|
||||
dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF,
|
||||
0x10, /* VBP_RGB_GEN */
|
||||
0x10, /* VFP_RGB_GEN */
|
||||
0x05, /* DE_BP_RGB_GEN */
|
||||
0x05, /* DE_FP_RGB_GEN */
|
||||
/* The rest is undocumented in ST7703 datasheet */
|
||||
0x03, 0xFF,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF,
|
||||
0x10, /* VBP_RGB_GEN */
|
||||
0x10, /* VFP_RGB_GEN */
|
||||
0x05, /* DE_BP_RGB_GEN */
|
||||
0x05, /* DE_FP_RGB_GEN */
|
||||
/* The rest is undocumented in ST7703 datasheet */
|
||||
0x03, 0xFF,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00);
|
||||
|
||||
/* Source driving settings. */
|
||||
dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR,
|
||||
0x73, /* N_POPON */
|
||||
0x73, /* N_NOPON */
|
||||
0x50, /* I_POPON */
|
||||
0x50, /* I_NOPON */
|
||||
0x00, /* SCR[31,24] */
|
||||
0xC0, /* SCR[23,16] */
|
||||
0x08, /* SCR[15,8] */
|
||||
0x70, /* SCR[7,0] */
|
||||
0x00 /* Undocumented */);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR,
|
||||
0x73, /* N_POPON */
|
||||
0x73, /* N_NOPON */
|
||||
0x50, /* I_POPON */
|
||||
0x50, /* I_NOPON */
|
||||
0x00, /* SCR[31,24] */
|
||||
0xC0, /* SCR[23,16] */
|
||||
0x08, /* SCR[15,8] */
|
||||
0x70, /* SCR[7,0] */
|
||||
0x00 /* Undocumented */);
|
||||
|
||||
/* NVDDD_SEL = -1.8V, VDDD_SEL = out of range (possibly 1.9V?) */
|
||||
dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E);
|
||||
|
||||
/*
|
||||
* SS_PANEL = 1 (reverse scan), GS_PANEL = 0 (normal scan)
|
||||
* REV_PANEL = 1 (normally black panel), BGR_PANEL = 1 (BGR)
|
||||
*/
|
||||
dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B);
|
||||
|
||||
/* Zig-Zag Type C column inversion. */
|
||||
dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
|
||||
|
||||
/* Set display resolution. */
|
||||
dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP,
|
||||
0xF0, /* NL = 240 */
|
||||
0x12, /* RES_V_LSB = 0, BLK_CON = VSSD,
|
||||
* RESO_SEL = 720RGB
|
||||
*/
|
||||
0xF0 /* WHITE_GND_EN = 1 (GND),
|
||||
* WHITE_FRAME_SEL = 7 frames,
|
||||
* ISC = 0 frames
|
||||
*/);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP,
|
||||
0xF0, /* NL = 240 */
|
||||
0x12, /* RES_V_LSB = 0, BLK_CON = VSSD,
|
||||
* RESO_SEL = 720RGB
|
||||
*/
|
||||
0xF0 /* WHITE_GND_EN = 1 (GND),
|
||||
* WHITE_FRAME_SEL = 7 frames,
|
||||
* ISC = 0 frames
|
||||
*/);
|
||||
|
||||
dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ,
|
||||
0x00, /* PNOEQ */
|
||||
0x00, /* NNOEQ */
|
||||
0x0B, /* PEQGND */
|
||||
0x0B, /* NEQGND */
|
||||
0x10, /* PEQVCI */
|
||||
0x10, /* NEQVCI */
|
||||
0x00, /* PEQVCI1 */
|
||||
0x00, /* NEQVCI1 */
|
||||
0x00, /* reserved */
|
||||
0x00, /* reserved */
|
||||
0xFF, /* reserved */
|
||||
0x00, /* reserved */
|
||||
0xC0, /* ESD_DET_DATA_WHITE = 1, ESD_WHITE_EN = 1 */
|
||||
0x10 /* SLPIN_OPTION = 1 (no need vsync after sleep-in)
|
||||
* VEDIO_NO_CHECK_EN = 0
|
||||
* ESD_WHITE_GND_EN = 0
|
||||
* ESD_DET_TIME_SEL = 0 frames
|
||||
*/);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ,
|
||||
0x00, /* PNOEQ */
|
||||
0x00, /* NNOEQ */
|
||||
0x0B, /* PEQGND */
|
||||
0x0B, /* NEQGND */
|
||||
0x10, /* PEQVCI */
|
||||
0x10, /* NEQVCI */
|
||||
0x00, /* PEQVCI1 */
|
||||
0x00, /* NEQVCI1 */
|
||||
0x00, /* reserved */
|
||||
0x00, /* reserved */
|
||||
0xFF, /* reserved */
|
||||
0x00, /* reserved */
|
||||
0xC0, /* ESD_DET_DATA_WHITE = 1, ESD_WHITE_EN = 1 */
|
||||
0x10 /* SLPIN_OPTION = 1 (no need vsync after sleep-in)
|
||||
* VEDIO_NO_CHECK_EN = 0
|
||||
* ESD_WHITE_GND_EN = 0
|
||||
* ESD_DET_TIME_SEL = 0 frames
|
||||
*/);
|
||||
|
||||
/* Undocumented command. */
|
||||
dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_C6, 0x01, 0x00, 0xFF, 0xFF, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_C6, 0x01, 0x00, 0xFF, 0xFF, 0x00);
|
||||
|
||||
dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER,
|
||||
0x74, /* VBTHS, VBTLS: VGH = 17V, VBL = -11V */
|
||||
0x00, /* FBOFF_VGH = 0, FBOFF_VGL = 0 */
|
||||
0x32, /* VRP */
|
||||
0x32, /* VRN */
|
||||
0x77, /* reserved */
|
||||
0xF1, /* APS = 1 (small),
|
||||
* VGL_DET_EN = 1, VGH_DET_EN = 1,
|
||||
* VGL_TURBO = 1, VGH_TURBO = 1
|
||||
*/
|
||||
0xFF, /* VGH1_L_DIV, VGL1_L_DIV (1.5MHz) */
|
||||
0xFF, /* VGH1_R_DIV, VGL1_R_DIV (1.5MHz) */
|
||||
0xCC, /* VGH2_L_DIV, VGL2_L_DIV (2.6MHz) */
|
||||
0xCC, /* VGH2_R_DIV, VGL2_R_DIV (2.6MHz) */
|
||||
0x77, /* VGH3_L_DIV, VGL3_L_DIV (4.5MHz) */
|
||||
0x77 /* VGH3_R_DIV, VGL3_R_DIV (4.5MHz) */);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER,
|
||||
0x74, /* VBTHS, VBTLS: VGH = 17V, VBL = -11V */
|
||||
0x00, /* FBOFF_VGH = 0, FBOFF_VGL = 0 */
|
||||
0x32, /* VRP */
|
||||
0x32, /* VRN */
|
||||
0x77, /* reserved */
|
||||
0xF1, /* APS = 1 (small),
|
||||
* VGL_DET_EN = 1, VGH_DET_EN = 1,
|
||||
* VGL_TURBO = 1, VGH_TURBO = 1
|
||||
*/
|
||||
0xFF, /* VGH1_L_DIV, VGL1_L_DIV (1.5MHz) */
|
||||
0xFF, /* VGH1_R_DIV, VGL1_R_DIV (1.5MHz) */
|
||||
0xCC, /* VGH2_L_DIV, VGL2_L_DIV (2.6MHz) */
|
||||
0xCC, /* VGH2_R_DIV, VGL2_R_DIV (2.6MHz) */
|
||||
0x77, /* VGH3_L_DIV, VGL3_L_DIV (4.5MHz) */
|
||||
0x77 /* VGH3_R_DIV, VGL3_R_DIV (4.5MHz) */);
|
||||
|
||||
/* Reference voltage. */
|
||||
dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP,
|
||||
0x07, /* VREF_SEL = 4.2V */
|
||||
0x07 /* NVREF_SEL = 4.2V */);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP,
|
||||
0x07, /* VREF_SEL = 4.2V */
|
||||
0x07 /* NVREF_SEL = 4.2V */);
|
||||
msleep(20);
|
||||
|
||||
dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM,
|
||||
0x2C, /* VCOMDC_F = -0.67V */
|
||||
0x2C /* VCOMDC_B = -0.67V */);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM,
|
||||
0x2C, /* VCOMDC_F = -0.67V */
|
||||
0x2C /* VCOMDC_B = -0.67V */);
|
||||
|
||||
/* Undocumented command. */
|
||||
dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
|
||||
|
||||
/* This command is to set forward GIP timing. */
|
||||
dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1,
|
||||
0x82, 0x10, 0x06, 0x05, 0xA2, 0x0A, 0xA5, 0x12,
|
||||
0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
|
||||
0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64,
|
||||
0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1,
|
||||
0x82, 0x10, 0x06, 0x05, 0xA2, 0x0A, 0xA5, 0x12,
|
||||
0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
|
||||
0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64,
|
||||
0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
|
||||
/* This command is to set backward GIP timing. */
|
||||
dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2,
|
||||
0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13,
|
||||
0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0A,
|
||||
0xA5, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2,
|
||||
0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13,
|
||||
0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0A,
|
||||
0xA5, 0x00, 0x00, 0x00, 0x00);
|
||||
|
||||
/* Adjust the gamma characteristics of the panel. */
|
||||
dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA,
|
||||
0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41, 0x35,
|
||||
0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12, 0x12,
|
||||
0x18, 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41,
|
||||
0x35, 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12,
|
||||
0x12, 0x18);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA,
|
||||
0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41, 0x35,
|
||||
0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12, 0x12,
|
||||
0x18, 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41,
|
||||
0x35, 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12,
|
||||
0x12, 0x18);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -499,7 +482,7 @@ static int allpixelson_set(void *data, u64 val)
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
|
||||
dev_dbg(ctx->dev, "Setting all pixels on\n");
|
||||
dsi_generic_write_seq(dsi, ST7703_CMD_ALL_PIXEL_ON);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_ALL_PIXEL_ON);
|
||||
msleep(val * 1000);
|
||||
/* Reset the panel to get video back */
|
||||
drm_panel_disable(&ctx->panel);
|
||||
|
@ -33,14 +33,6 @@ struct truly_nt35521 *to_truly_nt35521(struct drm_panel *panel)
|
||||
return container_of(panel, struct truly_nt35521, panel);
|
||||
}
|
||||
|
||||
#define dsi_generic_write_seq(dsi, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
static void truly_nt35521_reset(struct truly_nt35521 *ctx)
|
||||
{
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
@ -59,200 +51,200 @@ static int truly_nt35521_on(struct truly_nt35521 *ctx)
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xff, 0xaa, 0x55, 0xa5, 0x80);
|
||||
dsi_generic_write_seq(dsi, 0x6f, 0x11, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xf7, 0x20, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0x6f, 0x01);
|
||||
dsi_generic_write_seq(dsi, 0xb1, 0x21);
|
||||
dsi_generic_write_seq(dsi, 0xbd, 0x01, 0xa0, 0x10, 0x08, 0x01);
|
||||
dsi_generic_write_seq(dsi, 0xb8, 0x01, 0x02, 0x0c, 0x02);
|
||||
dsi_generic_write_seq(dsi, 0xbb, 0x11, 0x11);
|
||||
dsi_generic_write_seq(dsi, 0xbc, 0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xb6, 0x02);
|
||||
dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x01);
|
||||
dsi_generic_write_seq(dsi, 0xb0, 0x09, 0x09);
|
||||
dsi_generic_write_seq(dsi, 0xb1, 0x09, 0x09);
|
||||
dsi_generic_write_seq(dsi, 0xbc, 0x8c, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xbd, 0x8c, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xca, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xc0, 0x04);
|
||||
dsi_generic_write_seq(dsi, 0xbe, 0xb5);
|
||||
dsi_generic_write_seq(dsi, 0xb3, 0x35, 0x35);
|
||||
dsi_generic_write_seq(dsi, 0xb4, 0x25, 0x25);
|
||||
dsi_generic_write_seq(dsi, 0xb9, 0x43, 0x43);
|
||||
dsi_generic_write_seq(dsi, 0xba, 0x24, 0x24);
|
||||
dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x02);
|
||||
dsi_generic_write_seq(dsi, 0xee, 0x03);
|
||||
dsi_generic_write_seq(dsi, 0xb0,
|
||||
0x00, 0xb2, 0x00, 0xb3, 0x00, 0xb6, 0x00, 0xc3,
|
||||
0x00, 0xce, 0x00, 0xe1, 0x00, 0xf3, 0x01, 0x11);
|
||||
dsi_generic_write_seq(dsi, 0xb1,
|
||||
0x01, 0x2e, 0x01, 0x5c, 0x01, 0x82, 0x01, 0xc3,
|
||||
0x01, 0xfe, 0x02, 0x00, 0x02, 0x37, 0x02, 0x77);
|
||||
dsi_generic_write_seq(dsi, 0xb2,
|
||||
0x02, 0xa1, 0x02, 0xd7, 0x02, 0xfe, 0x03, 0x2c,
|
||||
0x03, 0x4b, 0x03, 0x63, 0x03, 0x8f, 0x03, 0x90);
|
||||
dsi_generic_write_seq(dsi, 0xb3, 0x03, 0x96, 0x03, 0x98);
|
||||
dsi_generic_write_seq(dsi, 0xb4,
|
||||
0x00, 0x81, 0x00, 0x8b, 0x00, 0x9c, 0x00, 0xa9,
|
||||
0x00, 0xb5, 0x00, 0xcb, 0x00, 0xdf, 0x01, 0x02);
|
||||
dsi_generic_write_seq(dsi, 0xb5,
|
||||
0x01, 0x1f, 0x01, 0x51, 0x01, 0x7a, 0x01, 0xbf,
|
||||
0x01, 0xfa, 0x01, 0xfc, 0x02, 0x34, 0x02, 0x76);
|
||||
dsi_generic_write_seq(dsi, 0xb6,
|
||||
0x02, 0x9f, 0x02, 0xd7, 0x02, 0xfc, 0x03, 0x2c,
|
||||
0x03, 0x4a, 0x03, 0x63, 0x03, 0x8f, 0x03, 0xa2);
|
||||
dsi_generic_write_seq(dsi, 0xb7, 0x03, 0xb8, 0x03, 0xba);
|
||||
dsi_generic_write_seq(dsi, 0xb8,
|
||||
0x00, 0x01, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x2a,
|
||||
0x00, 0x41, 0x00, 0x67, 0x00, 0x87, 0x00, 0xb9);
|
||||
dsi_generic_write_seq(dsi, 0xb9,
|
||||
0x00, 0xe2, 0x01, 0x22, 0x01, 0x54, 0x01, 0xa3,
|
||||
0x01, 0xe6, 0x01, 0xe7, 0x02, 0x24, 0x02, 0x67);
|
||||
dsi_generic_write_seq(dsi, 0xba,
|
||||
0x02, 0x93, 0x02, 0xcd, 0x02, 0xf6, 0x03, 0x31,
|
||||
0x03, 0x6c, 0x03, 0xe9, 0x03, 0xef, 0x03, 0xf4);
|
||||
dsi_generic_write_seq(dsi, 0xbb, 0x03, 0xf6, 0x03, 0xf7);
|
||||
dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x03);
|
||||
dsi_generic_write_seq(dsi, 0xb0, 0x22, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xb1, 0x22, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xb2, 0x05, 0x00, 0x60, 0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xb3, 0x05, 0x00, 0x60, 0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xb4, 0x05, 0x00, 0x60, 0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xb5, 0x05, 0x00, 0x60, 0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xba, 0x53, 0x00, 0x60, 0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xbb, 0x53, 0x00, 0x60, 0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xbc, 0x53, 0x00, 0x60, 0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xbd, 0x53, 0x00, 0x60, 0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xc0, 0x00, 0x34, 0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xc1, 0x00, 0x00, 0x34, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xc2, 0x00, 0x00, 0x34, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xc3, 0x00, 0x00, 0x34, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xc4, 0x60);
|
||||
dsi_generic_write_seq(dsi, 0xc5, 0xc0);
|
||||
dsi_generic_write_seq(dsi, 0xc6, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xc7, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x05);
|
||||
dsi_generic_write_seq(dsi, 0xb0, 0x17, 0x06);
|
||||
dsi_generic_write_seq(dsi, 0xb1, 0x17, 0x06);
|
||||
dsi_generic_write_seq(dsi, 0xb2, 0x17, 0x06);
|
||||
dsi_generic_write_seq(dsi, 0xb3, 0x17, 0x06);
|
||||
dsi_generic_write_seq(dsi, 0xb4, 0x17, 0x06);
|
||||
dsi_generic_write_seq(dsi, 0xb5, 0x17, 0x06);
|
||||
dsi_generic_write_seq(dsi, 0xb6, 0x17, 0x06);
|
||||
dsi_generic_write_seq(dsi, 0xb7, 0x17, 0x06);
|
||||
dsi_generic_write_seq(dsi, 0xb8, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xb9, 0x00, 0x03);
|
||||
dsi_generic_write_seq(dsi, 0xba, 0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xbb, 0x02, 0x03);
|
||||
dsi_generic_write_seq(dsi, 0xbc, 0x02, 0x03);
|
||||
dsi_generic_write_seq(dsi, 0xbd, 0x03, 0x03, 0x00, 0x03, 0x03);
|
||||
dsi_generic_write_seq(dsi, 0xc0, 0x0b);
|
||||
dsi_generic_write_seq(dsi, 0xc1, 0x09);
|
||||
dsi_generic_write_seq(dsi, 0xc2, 0xa6);
|
||||
dsi_generic_write_seq(dsi, 0xc3, 0x05);
|
||||
dsi_generic_write_seq(dsi, 0xc4, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xc5, 0x02);
|
||||
dsi_generic_write_seq(dsi, 0xc6, 0x22);
|
||||
dsi_generic_write_seq(dsi, 0xc7, 0x03);
|
||||
dsi_generic_write_seq(dsi, 0xc8, 0x07, 0x20);
|
||||
dsi_generic_write_seq(dsi, 0xc9, 0x03, 0x20);
|
||||
dsi_generic_write_seq(dsi, 0xca, 0x01, 0x60);
|
||||
dsi_generic_write_seq(dsi, 0xcb, 0x01, 0x60);
|
||||
dsi_generic_write_seq(dsi, 0xcc, 0x00, 0x00, 0x02);
|
||||
dsi_generic_write_seq(dsi, 0xcd, 0x00, 0x00, 0x02);
|
||||
dsi_generic_write_seq(dsi, 0xce, 0x00, 0x00, 0x02);
|
||||
dsi_generic_write_seq(dsi, 0xcf, 0x00, 0x00, 0x02);
|
||||
dsi_generic_write_seq(dsi, 0xd1, 0x00, 0x05, 0x01, 0x07, 0x10);
|
||||
dsi_generic_write_seq(dsi, 0xd2, 0x10, 0x05, 0x05, 0x03, 0x10);
|
||||
dsi_generic_write_seq(dsi, 0xd3, 0x20, 0x00, 0x43, 0x07, 0x10);
|
||||
dsi_generic_write_seq(dsi, 0xd4, 0x30, 0x00, 0x43, 0x07, 0x10);
|
||||
dsi_generic_write_seq(dsi, 0xd0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xd5,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xd6,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xd7,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xe5, 0x06);
|
||||
dsi_generic_write_seq(dsi, 0xe6, 0x06);
|
||||
dsi_generic_write_seq(dsi, 0xe7, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xe8, 0x06);
|
||||
dsi_generic_write_seq(dsi, 0xe9, 0x06);
|
||||
dsi_generic_write_seq(dsi, 0xea, 0x06);
|
||||
dsi_generic_write_seq(dsi, 0xeb, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xec, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xed, 0x30);
|
||||
dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x06);
|
||||
dsi_generic_write_seq(dsi, 0xb0, 0x31, 0x31);
|
||||
dsi_generic_write_seq(dsi, 0xb1, 0x31, 0x31);
|
||||
dsi_generic_write_seq(dsi, 0xb2, 0x2d, 0x2e);
|
||||
dsi_generic_write_seq(dsi, 0xb3, 0x31, 0x34);
|
||||
dsi_generic_write_seq(dsi, 0xb4, 0x29, 0x2a);
|
||||
dsi_generic_write_seq(dsi, 0xb5, 0x12, 0x10);
|
||||
dsi_generic_write_seq(dsi, 0xb6, 0x18, 0x16);
|
||||
dsi_generic_write_seq(dsi, 0xb7, 0x00, 0x02);
|
||||
dsi_generic_write_seq(dsi, 0xb8, 0x08, 0x31);
|
||||
dsi_generic_write_seq(dsi, 0xb9, 0x31, 0x31);
|
||||
dsi_generic_write_seq(dsi, 0xba, 0x31, 0x31);
|
||||
dsi_generic_write_seq(dsi, 0xbb, 0x31, 0x08);
|
||||
dsi_generic_write_seq(dsi, 0xbc, 0x03, 0x01);
|
||||
dsi_generic_write_seq(dsi, 0xbd, 0x17, 0x19);
|
||||
dsi_generic_write_seq(dsi, 0xbe, 0x11, 0x13);
|
||||
dsi_generic_write_seq(dsi, 0xbf, 0x2a, 0x29);
|
||||
dsi_generic_write_seq(dsi, 0xc0, 0x34, 0x31);
|
||||
dsi_generic_write_seq(dsi, 0xc1, 0x2e, 0x2d);
|
||||
dsi_generic_write_seq(dsi, 0xc2, 0x31, 0x31);
|
||||
dsi_generic_write_seq(dsi, 0xc3, 0x31, 0x31);
|
||||
dsi_generic_write_seq(dsi, 0xc4, 0x31, 0x31);
|
||||
dsi_generic_write_seq(dsi, 0xc5, 0x31, 0x31);
|
||||
dsi_generic_write_seq(dsi, 0xc6, 0x2e, 0x2d);
|
||||
dsi_generic_write_seq(dsi, 0xc7, 0x31, 0x34);
|
||||
dsi_generic_write_seq(dsi, 0xc8, 0x29, 0x2a);
|
||||
dsi_generic_write_seq(dsi, 0xc9, 0x17, 0x19);
|
||||
dsi_generic_write_seq(dsi, 0xca, 0x11, 0x13);
|
||||
dsi_generic_write_seq(dsi, 0xcb, 0x03, 0x01);
|
||||
dsi_generic_write_seq(dsi, 0xcc, 0x08, 0x31);
|
||||
dsi_generic_write_seq(dsi, 0xcd, 0x31, 0x31);
|
||||
dsi_generic_write_seq(dsi, 0xce, 0x31, 0x31);
|
||||
dsi_generic_write_seq(dsi, 0xcf, 0x31, 0x08);
|
||||
dsi_generic_write_seq(dsi, 0xd0, 0x00, 0x02);
|
||||
dsi_generic_write_seq(dsi, 0xd1, 0x12, 0x10);
|
||||
dsi_generic_write_seq(dsi, 0xd2, 0x18, 0x16);
|
||||
dsi_generic_write_seq(dsi, 0xd3, 0x2a, 0x29);
|
||||
dsi_generic_write_seq(dsi, 0xd4, 0x34, 0x31);
|
||||
dsi_generic_write_seq(dsi, 0xd5, 0x2d, 0x2e);
|
||||
dsi_generic_write_seq(dsi, 0xd6, 0x31, 0x31);
|
||||
dsi_generic_write_seq(dsi, 0xd7, 0x31, 0x31);
|
||||
dsi_generic_write_seq(dsi, 0xe5, 0x31, 0x31);
|
||||
dsi_generic_write_seq(dsi, 0xe6, 0x31, 0x31);
|
||||
dsi_generic_write_seq(dsi, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xd9, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xe7, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0x6f, 0x02);
|
||||
dsi_generic_write_seq(dsi, 0xf7, 0x47);
|
||||
dsi_generic_write_seq(dsi, 0x6f, 0x0a);
|
||||
dsi_generic_write_seq(dsi, 0xf7, 0x02);
|
||||
dsi_generic_write_seq(dsi, 0x6f, 0x17);
|
||||
dsi_generic_write_seq(dsi, 0xf4, 0x60);
|
||||
dsi_generic_write_seq(dsi, 0x6f, 0x01);
|
||||
dsi_generic_write_seq(dsi, 0xf9, 0x46);
|
||||
dsi_generic_write_seq(dsi, 0x6f, 0x11);
|
||||
dsi_generic_write_seq(dsi, 0xf3, 0x01);
|
||||
dsi_generic_write_seq(dsi, 0x35, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xd9, 0x02, 0x03, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0xb1, 0x6c, 0x21);
|
||||
dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, 0x35, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xff, 0xaa, 0x55, 0xa5, 0x80);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x6f, 0x11, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf7, 0x20, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x6f, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb1, 0x21);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbd, 0x01, 0xa0, 0x10, 0x08, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb8, 0x01, 0x02, 0x0c, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbb, 0x11, 0x11);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbc, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb6, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb0, 0x09, 0x09);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb1, 0x09, 0x09);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbc, 0x8c, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbd, 0x8c, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xca, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc0, 0x04);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbe, 0xb5);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb3, 0x35, 0x35);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb4, 0x25, 0x25);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb9, 0x43, 0x43);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xba, 0x24, 0x24);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xee, 0x03);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb0,
|
||||
0x00, 0xb2, 0x00, 0xb3, 0x00, 0xb6, 0x00, 0xc3,
|
||||
0x00, 0xce, 0x00, 0xe1, 0x00, 0xf3, 0x01, 0x11);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb1,
|
||||
0x01, 0x2e, 0x01, 0x5c, 0x01, 0x82, 0x01, 0xc3,
|
||||
0x01, 0xfe, 0x02, 0x00, 0x02, 0x37, 0x02, 0x77);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb2,
|
||||
0x02, 0xa1, 0x02, 0xd7, 0x02, 0xfe, 0x03, 0x2c,
|
||||
0x03, 0x4b, 0x03, 0x63, 0x03, 0x8f, 0x03, 0x90);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb3, 0x03, 0x96, 0x03, 0x98);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb4,
|
||||
0x00, 0x81, 0x00, 0x8b, 0x00, 0x9c, 0x00, 0xa9,
|
||||
0x00, 0xb5, 0x00, 0xcb, 0x00, 0xdf, 0x01, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb5,
|
||||
0x01, 0x1f, 0x01, 0x51, 0x01, 0x7a, 0x01, 0xbf,
|
||||
0x01, 0xfa, 0x01, 0xfc, 0x02, 0x34, 0x02, 0x76);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb6,
|
||||
0x02, 0x9f, 0x02, 0xd7, 0x02, 0xfc, 0x03, 0x2c,
|
||||
0x03, 0x4a, 0x03, 0x63, 0x03, 0x8f, 0x03, 0xa2);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb7, 0x03, 0xb8, 0x03, 0xba);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb8,
|
||||
0x00, 0x01, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x2a,
|
||||
0x00, 0x41, 0x00, 0x67, 0x00, 0x87, 0x00, 0xb9);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb9,
|
||||
0x00, 0xe2, 0x01, 0x22, 0x01, 0x54, 0x01, 0xa3,
|
||||
0x01, 0xe6, 0x01, 0xe7, 0x02, 0x24, 0x02, 0x67);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xba,
|
||||
0x02, 0x93, 0x02, 0xcd, 0x02, 0xf6, 0x03, 0x31,
|
||||
0x03, 0x6c, 0x03, 0xe9, 0x03, 0xef, 0x03, 0xf4);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbb, 0x03, 0xf6, 0x03, 0xf7);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x03);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb0, 0x22, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb1, 0x22, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb2, 0x05, 0x00, 0x60, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb3, 0x05, 0x00, 0x60, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb4, 0x05, 0x00, 0x60, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb5, 0x05, 0x00, 0x60, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xba, 0x53, 0x00, 0x60, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbb, 0x53, 0x00, 0x60, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbc, 0x53, 0x00, 0x60, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbd, 0x53, 0x00, 0x60, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc0, 0x00, 0x34, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc1, 0x00, 0x00, 0x34, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc2, 0x00, 0x00, 0x34, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc3, 0x00, 0x00, 0x34, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc4, 0x60);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc5, 0xc0);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc6, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc7, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x05);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb0, 0x17, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb1, 0x17, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb2, 0x17, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb3, 0x17, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb4, 0x17, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb5, 0x17, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb6, 0x17, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb7, 0x17, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb8, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb9, 0x00, 0x03);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xba, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbb, 0x02, 0x03);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbc, 0x02, 0x03);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbd, 0x03, 0x03, 0x00, 0x03, 0x03);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc0, 0x0b);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc1, 0x09);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc2, 0xa6);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc3, 0x05);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc4, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc5, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc6, 0x22);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc7, 0x03);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc8, 0x07, 0x20);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc9, 0x03, 0x20);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xca, 0x01, 0x60);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xcb, 0x01, 0x60);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xcc, 0x00, 0x00, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xcd, 0x00, 0x00, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xce, 0x00, 0x00, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xcf, 0x00, 0x00, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd1, 0x00, 0x05, 0x01, 0x07, 0x10);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd2, 0x10, 0x05, 0x05, 0x03, 0x10);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd3, 0x20, 0x00, 0x43, 0x07, 0x10);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd4, 0x30, 0x00, 0x43, 0x07, 0x10);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd5,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd6,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd7,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xe5, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xe6, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xe7, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xe8, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xe9, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xea, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xeb, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xec, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xed, 0x30);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb0, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb1, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb2, 0x2d, 0x2e);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb3, 0x31, 0x34);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb4, 0x29, 0x2a);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb5, 0x12, 0x10);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb6, 0x18, 0x16);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb7, 0x00, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb8, 0x08, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb9, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xba, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbb, 0x31, 0x08);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbc, 0x03, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbd, 0x17, 0x19);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbe, 0x11, 0x13);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbf, 0x2a, 0x29);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc0, 0x34, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc1, 0x2e, 0x2d);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc2, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc3, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc4, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc5, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc6, 0x2e, 0x2d);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc7, 0x31, 0x34);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc8, 0x29, 0x2a);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc9, 0x17, 0x19);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xca, 0x11, 0x13);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xcb, 0x03, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xcc, 0x08, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xcd, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xce, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xcf, 0x31, 0x08);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd0, 0x00, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd1, 0x12, 0x10);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd2, 0x18, 0x16);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd3, 0x2a, 0x29);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd4, 0x34, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd5, 0x2d, 0x2e);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd6, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd7, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xe5, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xe6, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd9, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xe7, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x6f, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf7, 0x47);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x6f, 0x0a);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf7, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x6f, 0x17);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf4, 0x60);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x6f, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf9, 0x46);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x6f, 0x11);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf3, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x35, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd9, 0x02, 0x03, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb1, 0x6c, 0x21);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x35, 0x00);
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
@ -268,7 +260,7 @@ static int truly_nt35521_on(struct truly_nt35521 *ctx)
|
||||
}
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
dsi_generic_write_seq(dsi, 0x53, 0x24);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x53, 0x24);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
358
drivers/gpu/drm/panel/panel-visionox-vtdr6130.c
Normal file
358
drivers/gpu/drm/panel/panel-visionox-vtdr6130.c
Normal file
@ -0,0 +1,358 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// Copyright (c) 2023, Linaro Limited
|
||||
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <drm/display/drm_dsc.h>
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
struct visionox_vtdr6130 {
|
||||
struct drm_panel panel;
|
||||
struct mipi_dsi_device *dsi;
|
||||
struct gpio_desc *reset_gpio;
|
||||
struct regulator_bulk_data supplies[3];
|
||||
bool prepared;
|
||||
};
|
||||
|
||||
static inline struct visionox_vtdr6130 *to_visionox_vtdr6130(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct visionox_vtdr6130, panel);
|
||||
}
|
||||
|
||||
static void visionox_vtdr6130_reset(struct visionox_vtdr6130 *ctx)
|
||||
{
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
usleep_range(10000, 11000);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
usleep_range(10000, 11000);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
usleep_range(10000, 11000);
|
||||
}
|
||||
|
||||
static int visionox_vtdr6130_on(struct visionox_vtdr6130 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x20);
|
||||
mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0x59, 0x09);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0x6c, 0x01);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0x6d, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0x6f, 0x01);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0x70,
|
||||
0x12, 0x00, 0x00, 0xab, 0x30, 0x80, 0x09, 0x60, 0x04,
|
||||
0x38, 0x00, 0x28, 0x02, 0x1c, 0x02, 0x1c, 0x02, 0x00,
|
||||
0x02, 0x0e, 0x00, 0x20, 0x03, 0xdd, 0x00, 0x07, 0x00,
|
||||
0x0c, 0x02, 0x77, 0x02, 0x8b, 0x18, 0x00, 0x10, 0xf0,
|
||||
0x07, 0x10, 0x20, 0x00, 0x06, 0x0f, 0x0f, 0x33, 0x0e,
|
||||
0x1c, 0x2a, 0x38, 0x46, 0x54, 0x62, 0x69, 0x70, 0x77,
|
||||
0x79, 0x7b, 0x7d, 0x7e, 0x02, 0x02, 0x22, 0x00, 0x2a,
|
||||
0x40, 0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8,
|
||||
0x3b, 0x38, 0x3b, 0x78, 0x3b, 0xb6, 0x4b, 0xb6, 0x4b,
|
||||
0xf4, 0x4b, 0xf4, 0x6c, 0x34, 0x84, 0x74, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xaa, 0x10);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb1,
|
||||
0x01, 0x38, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x01, 0x66,
|
||||
0x00, 0x14, 0x00, 0x14, 0x00, 0x01, 0x66, 0x00, 0x14,
|
||||
0x05, 0xcc, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xaa, 0x13);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xce,
|
||||
0x09, 0x11, 0x09, 0x11, 0x08, 0xc1, 0x07, 0xfa, 0x05,
|
||||
0xa4, 0x00, 0x3c, 0x00, 0x34, 0x00, 0x24, 0x00, 0x0c,
|
||||
0x00, 0x0c, 0x04, 0x00, 0x35);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xaa, 0x14);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x03, 0x33);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb4,
|
||||
0x00, 0x33, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
|
||||
0x3e, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb5,
|
||||
0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x06, 0x01);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0x00, 0x08, 0x09, 0x09, 0x09);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xbc,
|
||||
0x10, 0x00, 0x00, 0x06, 0x11, 0x09, 0x3b, 0x09, 0x47,
|
||||
0x09, 0x47, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xbe,
|
||||
0x10, 0x10, 0x00, 0x08, 0x22, 0x09, 0x19, 0x09, 0x25,
|
||||
0x09, 0x25, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xff, 0x5a, 0x80);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0x65, 0x14);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xfa, 0x08, 0x08, 0x08);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xff, 0x5a, 0x81);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0x65, 0x05);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xf3, 0x0f);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xaa, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xff, 0x5a, 0x82);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xf9, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xff, 0x51, 0x83);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0x65, 0x04);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xf8, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xff, 0x5a, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0x65, 0x01);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xf4, 0x9a);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xff, 0x5a, 0x00);
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(120);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(20);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int visionox_vtdr6130_off(struct visionox_vtdr6130 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_off(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display off: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(20);
|
||||
|
||||
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(120);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int visionox_vtdr6130_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct visionox_vtdr6130 *ctx = to_visionox_vtdr6130(panel);
|
||||
struct device *dev = &ctx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (ctx->prepared)
|
||||
return 0;
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies),
|
||||
ctx->supplies);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
visionox_vtdr6130_reset(ctx);
|
||||
|
||||
ret = visionox_vtdr6130_on(ctx);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to initialize panel: %d\n", ret);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->prepared = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int visionox_vtdr6130_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct visionox_vtdr6130 *ctx = to_visionox_vtdr6130(panel);
|
||||
struct device *dev = &ctx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (!ctx->prepared)
|
||||
return 0;
|
||||
|
||||
ret = visionox_vtdr6130_off(ctx);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
|
||||
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
|
||||
regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
|
||||
|
||||
ctx->prepared = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode visionox_vtdr6130_mode = {
|
||||
.clock = (1080 + 20 + 2 + 20) * (2400 + 20 + 2 + 18) * 144 / 1000,
|
||||
.hdisplay = 1080,
|
||||
.hsync_start = 1080 + 20,
|
||||
.hsync_end = 1080 + 20 + 2,
|
||||
.htotal = 1080 + 20 + 2 + 20,
|
||||
.vdisplay = 2400,
|
||||
.vsync_start = 2400 + 20,
|
||||
.vsync_end = 2400 + 20 + 2,
|
||||
.vtotal = 2400 + 20 + 2 + 18,
|
||||
.width_mm = 71,
|
||||
.height_mm = 157,
|
||||
};
|
||||
|
||||
static int visionox_vtdr6130_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev, &visionox_vtdr6130_mode);
|
||||
if (!mode)
|
||||
return -ENOMEM;
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
|
||||
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
||||
connector->display_info.width_mm = mode->width_mm;
|
||||
connector->display_info.height_mm = mode->height_mm;
|
||||
drm_mode_probed_add(connector, mode);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs visionox_vtdr6130_panel_funcs = {
|
||||
.prepare = visionox_vtdr6130_prepare,
|
||||
.unprepare = visionox_vtdr6130_unprepare,
|
||||
.get_modes = visionox_vtdr6130_get_modes,
|
||||
};
|
||||
|
||||
static int visionox_vtdr6130_bl_update_status(struct backlight_device *bl)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = bl_get_data(bl);
|
||||
u16 brightness = backlight_get_brightness(bl);
|
||||
/* Panel needs big-endian order of brightness value */
|
||||
u8 payload[2] = { brightness >> 8, brightness & 0xff };
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
|
||||
payload, sizeof(payload));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct backlight_ops visionox_vtdr6130_bl_ops = {
|
||||
.update_status = visionox_vtdr6130_bl_update_status,
|
||||
};
|
||||
|
||||
static struct backlight_device *
|
||||
visionox_vtdr6130_create_backlight(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
const struct backlight_properties props = {
|
||||
.type = BACKLIGHT_RAW,
|
||||
.brightness = 4095,
|
||||
.max_brightness = 4095,
|
||||
};
|
||||
|
||||
return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
|
||||
&visionox_vtdr6130_bl_ops, &props);
|
||||
}
|
||||
|
||||
static int visionox_vtdr6130_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
struct visionox_vtdr6130 *ctx;
|
||||
int ret;
|
||||
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
ctx->supplies[0].supply = "vddio";
|
||||
ctx->supplies[1].supply = "vci";
|
||||
ctx->supplies[2].supply = "vdd";
|
||||
|
||||
ret = devm_regulator_bulk_get(&dsi->dev, ARRAY_SIZE(ctx->supplies),
|
||||
ctx->supplies);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(ctx->reset_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
|
||||
"Failed to get reset-gpios\n");
|
||||
|
||||
ctx->dsi = dsi;
|
||||
mipi_dsi_set_drvdata(dsi, ctx);
|
||||
|
||||
dsi->lanes = 4;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_NO_EOT_PACKET |
|
||||
MIPI_DSI_CLOCK_NON_CONTINUOUS;
|
||||
|
||||
drm_panel_init(&ctx->panel, dev, &visionox_vtdr6130_panel_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
ctx->panel.backlight = visionox_vtdr6130_create_backlight(dsi);
|
||||
if (IS_ERR(ctx->panel.backlight))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
|
||||
"Failed to create backlight\n");
|
||||
|
||||
drm_panel_add(&ctx->panel);
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
|
||||
drm_panel_remove(&ctx->panel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void visionox_vtdr6130_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct visionox_vtdr6130 *ctx = mipi_dsi_get_drvdata(dsi);
|
||||
int ret;
|
||||
|
||||
ret = mipi_dsi_detach(dsi);
|
||||
if (ret < 0)
|
||||
dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
|
||||
|
||||
drm_panel_remove(&ctx->panel);
|
||||
}
|
||||
|
||||
static const struct of_device_id visionox_vtdr6130_of_match[] = {
|
||||
{ .compatible = "visionox,vtdr6130" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, visionox_vtdr6130_of_match);
|
||||
|
||||
static struct mipi_dsi_driver visionox_vtdr6130_driver = {
|
||||
.probe = visionox_vtdr6130_probe,
|
||||
.remove = visionox_vtdr6130_remove,
|
||||
.driver = {
|
||||
.name = "panel-visionox-vtdr6130",
|
||||
.of_match_table = visionox_vtdr6130_of_match,
|
||||
},
|
||||
};
|
||||
module_mipi_dsi_driver(visionox_vtdr6130_driver);
|
||||
|
||||
MODULE_AUTHOR("Neil Armstrong <neil.armstrong@linaro.org>");
|
||||
MODULE_DESCRIPTION("Panel driver for the Visionox VTDR6130 AMOLED DSI panel");
|
||||
MODULE_LICENSE("GPL");
|
@ -60,14 +60,6 @@ static inline struct xpp055c272 *panel_to_xpp055c272(struct drm_panel *panel)
|
||||
return container_of(panel, struct xpp055c272, panel);
|
||||
}
|
||||
|
||||
#define dsi_generic_write_seq(dsi, cmd, seq...) do { \
|
||||
static const u8 b[] = { cmd, seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_dcs_write_buffer(dsi, b, ARRAY_SIZE(b)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
static int xpp055c272_init_sequence(struct xpp055c272 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
@ -77,60 +69,60 @@ static int xpp055c272_init_sequence(struct xpp055c272 *ctx)
|
||||
* Init sequence was supplied by the panel vendor without much
|
||||
* documentation.
|
||||
*/
|
||||
dsi_generic_write_seq(dsi, XPP055C272_CMD_SETEXTC, 0xf1, 0x12, 0x83);
|
||||
dsi_generic_write_seq(dsi, XPP055C272_CMD_SETMIPI,
|
||||
0x33, 0x81, 0x05, 0xf9, 0x0e, 0x0e, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x25,
|
||||
0x00, 0x91, 0x0a, 0x00, 0x00, 0x02, 0x4f, 0x01,
|
||||
0x00, 0x00, 0x37);
|
||||
dsi_generic_write_seq(dsi, XPP055C272_CMD_SETPOWER_EXT, 0x25);
|
||||
dsi_generic_write_seq(dsi, XPP055C272_CMD_SETPCR, 0x02, 0x11, 0x00);
|
||||
dsi_generic_write_seq(dsi, XPP055C272_CMD_SETRGBIF,
|
||||
0x0c, 0x10, 0x0a, 0x50, 0x03, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, XPP055C272_CMD_SETSCR,
|
||||
0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70,
|
||||
0x00);
|
||||
dsi_generic_write_seq(dsi, XPP055C272_CMD_SETVDC, 0x46);
|
||||
dsi_generic_write_seq(dsi, XPP055C272_CMD_SETPANEL, 0x0b);
|
||||
dsi_generic_write_seq(dsi, XPP055C272_CMD_SETCYC, 0x80);
|
||||
dsi_generic_write_seq(dsi, XPP055C272_CMD_SETDISP, 0xc8, 0x12, 0x30);
|
||||
dsi_generic_write_seq(dsi, XPP055C272_CMD_SETEQ,
|
||||
0x07, 0x07, 0x0B, 0x0B, 0x03, 0x0B, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFF, 0x00, 0xC0, 0x10);
|
||||
dsi_generic_write_seq(dsi, XPP055C272_CMD_SETPOWER,
|
||||
0x53, 0x00, 0x1e, 0x1e, 0x77, 0xe1, 0xcc, 0xdd,
|
||||
0x67, 0x77, 0x33, 0x33);
|
||||
dsi_generic_write_seq(dsi, XPP055C272_CMD_SETECO, 0x00, 0x00, 0xff,
|
||||
0xff, 0x01, 0xff);
|
||||
dsi_generic_write_seq(dsi, XPP055C272_CMD_SETBGP, 0x09, 0x09);
|
||||
mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETEXTC, 0xf1, 0x12, 0x83);
|
||||
mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETMIPI,
|
||||
0x33, 0x81, 0x05, 0xf9, 0x0e, 0x0e, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x25,
|
||||
0x00, 0x91, 0x0a, 0x00, 0x00, 0x02, 0x4f, 0x01,
|
||||
0x00, 0x00, 0x37);
|
||||
mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETPOWER_EXT, 0x25);
|
||||
mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETPCR, 0x02, 0x11, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETRGBIF,
|
||||
0x0c, 0x10, 0x0a, 0x50, 0x03, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETSCR,
|
||||
0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70,
|
||||
0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETVDC, 0x46);
|
||||
mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETPANEL, 0x0b);
|
||||
mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETCYC, 0x80);
|
||||
mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETDISP, 0xc8, 0x12, 0x30);
|
||||
mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETEQ,
|
||||
0x07, 0x07, 0x0B, 0x0B, 0x03, 0x0B, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFF, 0x00, 0xC0, 0x10);
|
||||
mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETPOWER,
|
||||
0x53, 0x00, 0x1e, 0x1e, 0x77, 0xe1, 0xcc, 0xdd,
|
||||
0x67, 0x77, 0x33, 0x33);
|
||||
mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETECO, 0x00, 0x00, 0xff,
|
||||
0xff, 0x01, 0xff);
|
||||
mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETBGP, 0x09, 0x09);
|
||||
msleep(20);
|
||||
|
||||
dsi_generic_write_seq(dsi, XPP055C272_CMD_SETVCOM, 0x87, 0x95);
|
||||
dsi_generic_write_seq(dsi, XPP055C272_CMD_SETGIP1,
|
||||
0xc2, 0x10, 0x05, 0x05, 0x10, 0x05, 0xa0, 0x12,
|
||||
0x31, 0x23, 0x3f, 0x81, 0x0a, 0xa0, 0x37, 0x18,
|
||||
0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80,
|
||||
0x01, 0x00, 0x00, 0x00, 0x48, 0xf8, 0x86, 0x42,
|
||||
0x08, 0x88, 0x88, 0x80, 0x88, 0x88, 0x88, 0x58,
|
||||
0xf8, 0x87, 0x53, 0x18, 0x88, 0x88, 0x81, 0x88,
|
||||
0x88, 0x88, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, XPP055C272_CMD_SETGIP2,
|
||||
0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x1f, 0x88, 0x81, 0x35,
|
||||
0x78, 0x88, 0x88, 0x85, 0x88, 0x88, 0x88, 0x0f,
|
||||
0x88, 0x80, 0x24, 0x68, 0x88, 0x88, 0x84, 0x88,
|
||||
0x88, 0x88, 0x23, 0x10, 0x00, 0x00, 0x1c, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x05,
|
||||
0xa0, 0x00, 0x00, 0x00, 0x00);
|
||||
dsi_generic_write_seq(dsi, XPP055C272_CMD_SETGAMMA,
|
||||
0x00, 0x06, 0x08, 0x2a, 0x31, 0x3f, 0x38, 0x36,
|
||||
0x07, 0x0c, 0x0d, 0x11, 0x13, 0x12, 0x13, 0x11,
|
||||
0x18, 0x00, 0x06, 0x08, 0x2a, 0x31, 0x3f, 0x38,
|
||||
0x36, 0x07, 0x0c, 0x0d, 0x11, 0x13, 0x12, 0x13,
|
||||
0x11, 0x18);
|
||||
mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETVCOM, 0x87, 0x95);
|
||||
mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETGIP1,
|
||||
0xc2, 0x10, 0x05, 0x05, 0x10, 0x05, 0xa0, 0x12,
|
||||
0x31, 0x23, 0x3f, 0x81, 0x0a, 0xa0, 0x37, 0x18,
|
||||
0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80,
|
||||
0x01, 0x00, 0x00, 0x00, 0x48, 0xf8, 0x86, 0x42,
|
||||
0x08, 0x88, 0x88, 0x80, 0x88, 0x88, 0x88, 0x58,
|
||||
0xf8, 0x87, 0x53, 0x18, 0x88, 0x88, 0x81, 0x88,
|
||||
0x88, 0x88, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETGIP2,
|
||||
0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x1f, 0x88, 0x81, 0x35,
|
||||
0x78, 0x88, 0x88, 0x85, 0x88, 0x88, 0x88, 0x0f,
|
||||
0x88, 0x80, 0x24, 0x68, 0x88, 0x88, 0x84, 0x88,
|
||||
0x88, 0x88, 0x23, 0x10, 0x00, 0x00, 0x1c, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x05,
|
||||
0xa0, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETGAMMA,
|
||||
0x00, 0x06, 0x08, 0x2a, 0x31, 0x3f, 0x38, 0x36,
|
||||
0x07, 0x0c, 0x0d, 0x11, 0x13, 0x12, 0x13, 0x11,
|
||||
0x18, 0x00, 0x06, 0x08, 0x2a, 0x31, 0x3f, 0x38,
|
||||
0x36, 0x07, 0x0c, 0x0d, 0x11, 0x13, 0x12, 0x13,
|
||||
0x11, 0x18);
|
||||
|
||||
msleep(60);
|
||||
|
||||
|
@ -15,6 +15,8 @@ config DRM_RADEON
|
||||
select HWMON
|
||||
select BACKLIGHT_CLASS_DEVICE
|
||||
select INTERVAL_TREE
|
||||
select I2C
|
||||
select I2C_ALGOBIT
|
||||
# radeon depends on ACPI_VIDEO when ACPI is enabled, for select to work
|
||||
# ACPI_VIDEO's dependencies must also be selected.
|
||||
select INPUT if ACPI
|
||||
|
@ -32,16 +32,41 @@ struct convert_to_rgb565_result {
|
||||
const u16 expected_swab[TEST_BUF_SIZE];
|
||||
};
|
||||
|
||||
struct convert_to_xrgb1555_result {
|
||||
unsigned int dst_pitch;
|
||||
const u16 expected[TEST_BUF_SIZE];
|
||||
};
|
||||
|
||||
struct convert_to_argb1555_result {
|
||||
unsigned int dst_pitch;
|
||||
const u16 expected[TEST_BUF_SIZE];
|
||||
};
|
||||
|
||||
struct convert_to_rgba5551_result {
|
||||
unsigned int dst_pitch;
|
||||
const u16 expected[TEST_BUF_SIZE];
|
||||
};
|
||||
|
||||
struct convert_to_rgb888_result {
|
||||
unsigned int dst_pitch;
|
||||
const u8 expected[TEST_BUF_SIZE];
|
||||
};
|
||||
|
||||
struct convert_to_argb8888_result {
|
||||
unsigned int dst_pitch;
|
||||
const u32 expected[TEST_BUF_SIZE];
|
||||
};
|
||||
|
||||
struct convert_to_xrgb2101010_result {
|
||||
unsigned int dst_pitch;
|
||||
const u32 expected[TEST_BUF_SIZE];
|
||||
};
|
||||
|
||||
struct convert_to_argb2101010_result {
|
||||
unsigned int dst_pitch;
|
||||
const u32 expected[TEST_BUF_SIZE];
|
||||
};
|
||||
|
||||
struct convert_xrgb8888_case {
|
||||
const char *name;
|
||||
unsigned int pitch;
|
||||
@ -50,8 +75,13 @@ struct convert_xrgb8888_case {
|
||||
struct convert_to_gray8_result gray8_result;
|
||||
struct convert_to_rgb332_result rgb332_result;
|
||||
struct convert_to_rgb565_result rgb565_result;
|
||||
struct convert_to_xrgb1555_result xrgb1555_result;
|
||||
struct convert_to_argb1555_result argb1555_result;
|
||||
struct convert_to_rgba5551_result rgba5551_result;
|
||||
struct convert_to_rgb888_result rgb888_result;
|
||||
struct convert_to_argb8888_result argb8888_result;
|
||||
struct convert_to_xrgb2101010_result xrgb2101010_result;
|
||||
struct convert_to_argb2101010_result argb2101010_result;
|
||||
};
|
||||
|
||||
static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
|
||||
@ -73,14 +103,34 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
|
||||
.expected = { 0xF800 },
|
||||
.expected_swab = { 0x00F8 },
|
||||
},
|
||||
.xrgb1555_result = {
|
||||
.dst_pitch = 0,
|
||||
.expected = { 0x7C00 },
|
||||
},
|
||||
.argb1555_result = {
|
||||
.dst_pitch = 0,
|
||||
.expected = { 0xFC00 },
|
||||
},
|
||||
.rgba5551_result = {
|
||||
.dst_pitch = 0,
|
||||
.expected = { 0xF801 },
|
||||
},
|
||||
.rgb888_result = {
|
||||
.dst_pitch = 0,
|
||||
.expected = { 0x00, 0x00, 0xFF },
|
||||
},
|
||||
.argb8888_result = {
|
||||
.dst_pitch = 0,
|
||||
.expected = { 0xFFFF0000 },
|
||||
},
|
||||
.xrgb2101010_result = {
|
||||
.dst_pitch = 0,
|
||||
.expected = { 0x3FF00000 },
|
||||
},
|
||||
.argb2101010_result = {
|
||||
.dst_pitch = 0,
|
||||
.expected = { 0xFFF00000 },
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "single_pixel_clip_rectangle",
|
||||
@ -103,14 +153,34 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
|
||||
.expected = { 0xF800 },
|
||||
.expected_swab = { 0x00F8 },
|
||||
},
|
||||
.xrgb1555_result = {
|
||||
.dst_pitch = 0,
|
||||
.expected = { 0x7C00 },
|
||||
},
|
||||
.argb1555_result = {
|
||||
.dst_pitch = 0,
|
||||
.expected = { 0xFC00 },
|
||||
},
|
||||
.rgba5551_result = {
|
||||
.dst_pitch = 0,
|
||||
.expected = { 0xF801 },
|
||||
},
|
||||
.rgb888_result = {
|
||||
.dst_pitch = 0,
|
||||
.expected = { 0x00, 0x00, 0xFF },
|
||||
},
|
||||
.argb8888_result = {
|
||||
.dst_pitch = 0,
|
||||
.expected = { 0xFFFF0000 },
|
||||
},
|
||||
.xrgb2101010_result = {
|
||||
.dst_pitch = 0,
|
||||
.expected = { 0x3FF00000 },
|
||||
},
|
||||
.argb2101010_result = {
|
||||
.dst_pitch = 0,
|
||||
.expected = { 0xFFF00000 },
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Well known colors: White, black, red, green, blue, magenta,
|
||||
@ -160,6 +230,33 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
|
||||
0xE0FF, 0xFF07,
|
||||
},
|
||||
},
|
||||
.xrgb1555_result = {
|
||||
.dst_pitch = 0,
|
||||
.expected = {
|
||||
0x7FFF, 0x0000,
|
||||
0x7C00, 0x03E0,
|
||||
0x001F, 0x7C1F,
|
||||
0x7FE0, 0x03FF,
|
||||
},
|
||||
},
|
||||
.argb1555_result = {
|
||||
.dst_pitch = 0,
|
||||
.expected = {
|
||||
0xFFFF, 0x8000,
|
||||
0xFC00, 0x83E0,
|
||||
0x801F, 0xFC1F,
|
||||
0xFFE0, 0x83FF,
|
||||
},
|
||||
},
|
||||
.rgba5551_result = {
|
||||
.dst_pitch = 0,
|
||||
.expected = {
|
||||
0xFFFF, 0x0001,
|
||||
0xF801, 0x07C1,
|
||||
0x003F, 0xF83F,
|
||||
0xFFC1, 0x07FF,
|
||||
},
|
||||
},
|
||||
.rgb888_result = {
|
||||
.dst_pitch = 0,
|
||||
.expected = {
|
||||
@ -169,6 +266,15 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
|
||||
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
|
||||
},
|
||||
},
|
||||
.argb8888_result = {
|
||||
.dst_pitch = 0,
|
||||
.expected = {
|
||||
0xFFFFFFFF, 0xFF000000,
|
||||
0xFFFF0000, 0xFF00FF00,
|
||||
0xFF0000FF, 0xFFFF00FF,
|
||||
0xFFFFFF00, 0xFF00FFFF,
|
||||
},
|
||||
},
|
||||
.xrgb2101010_result = {
|
||||
.dst_pitch = 0,
|
||||
.expected = {
|
||||
@ -178,6 +284,15 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
|
||||
0x3FFFFC00, 0x000FFFFF,
|
||||
},
|
||||
},
|
||||
.argb2101010_result = {
|
||||
.dst_pitch = 0,
|
||||
.expected = {
|
||||
0xFFFFFFFF, 0xC0000000,
|
||||
0xFFF00000, 0xC00FFC00,
|
||||
0xC00003FF, 0xFFF003FF,
|
||||
0xFFFFFC00, 0xC00FFFFF,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Randomly picked colors. Full buffer within the clip area. */
|
||||
@ -218,6 +333,30 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
|
||||
0x00A8, 0x8E6B, 0x330A, 0x0000, 0x0000,
|
||||
},
|
||||
},
|
||||
.xrgb1555_result = {
|
||||
.dst_pitch = 10,
|
||||
.expected = {
|
||||
0x0513, 0x0920, 0x5400, 0x0000, 0x0000,
|
||||
0x35CE, 0x0513, 0x0920, 0x0000, 0x0000,
|
||||
0x5400, 0x35CE, 0x0513, 0x0000, 0x0000,
|
||||
},
|
||||
},
|
||||
.argb1555_result = {
|
||||
.dst_pitch = 10,
|
||||
.expected = {
|
||||
0x8513, 0x8920, 0xD400, 0x0000, 0x0000,
|
||||
0xB5CE, 0x8513, 0x8920, 0x0000, 0x0000,
|
||||
0xD400, 0xB5CE, 0x8513, 0x0000, 0x0000,
|
||||
},
|
||||
},
|
||||
.rgba5551_result = {
|
||||
.dst_pitch = 10,
|
||||
.expected = {
|
||||
0x0A27, 0x1241, 0xA801, 0x0000, 0x0000,
|
||||
0x6B9D, 0x0A27, 0x1241, 0x0000, 0x0000,
|
||||
0xA801, 0x6B9D, 0x0A27, 0x0000, 0x0000,
|
||||
},
|
||||
},
|
||||
.rgb888_result = {
|
||||
.dst_pitch = 15,
|
||||
.expected = {
|
||||
@ -229,6 +368,14 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
},
|
||||
},
|
||||
.argb8888_result = {
|
||||
.dst_pitch = 20,
|
||||
.expected = {
|
||||
0xFF0E449C, 0xFF114D05, 0xFFA80303, 0x00000000, 0x00000000,
|
||||
0xFF6C7073, 0xFF0E449C, 0xFF114D05, 0x00000000, 0x00000000,
|
||||
0xFFA80303, 0xFF6C7073, 0xFF0E449C, 0x00000000, 0x00000000,
|
||||
},
|
||||
},
|
||||
.xrgb2101010_result = {
|
||||
.dst_pitch = 20,
|
||||
.expected = {
|
||||
@ -237,6 +384,14 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
|
||||
0x2A20300C, 0x1B1705CD, 0x03844672, 0x00000000, 0x00000000,
|
||||
},
|
||||
},
|
||||
.argb2101010_result = {
|
||||
.dst_pitch = 20,
|
||||
.expected = {
|
||||
0xC3844672, 0xC444D414, 0xEA20300C, 0x00000000, 0x00000000,
|
||||
0xDB1705CD, 0xC3844672, 0xC444D414, 0x00000000, 0x00000000,
|
||||
0xEA20300C, 0xDB1705CD, 0xC3844672, 0x00000000, 0x00000000,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -264,7 +419,22 @@ static size_t conversion_buf_size(u32 dst_format, unsigned int dst_pitch,
|
||||
return dst_pitch * drm_rect_height(clip);
|
||||
}
|
||||
|
||||
static u32 *le32buf_to_cpu(struct kunit *test, const u32 *buf, size_t buf_size)
|
||||
static u16 *le16buf_to_cpu(struct kunit *test, const __le16 *buf, size_t buf_size)
|
||||
{
|
||||
u16 *dst = NULL;
|
||||
int n;
|
||||
|
||||
dst = kunit_kzalloc(test, sizeof(*dst) * buf_size, GFP_KERNEL);
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
for (n = 0; n < buf_size; n++)
|
||||
dst[n] = le16_to_cpu(buf[n]);
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
static u32 *le32buf_to_cpu(struct kunit *test, const __le32 *buf, size_t buf_size)
|
||||
{
|
||||
u32 *dst = NULL;
|
||||
int n;
|
||||
@ -279,6 +449,21 @@ static u32 *le32buf_to_cpu(struct kunit *test, const u32 *buf, size_t buf_size)
|
||||
return dst;
|
||||
}
|
||||
|
||||
static __le32 *cpubuf_to_le32(struct kunit *test, const u32 *buf, size_t buf_size)
|
||||
{
|
||||
__le32 *dst = NULL;
|
||||
int n;
|
||||
|
||||
dst = kunit_kzalloc(test, sizeof(*dst) * buf_size, GFP_KERNEL);
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
for (n = 0; n < buf_size; n++)
|
||||
dst[n] = cpu_to_le32(buf[n]);
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
static void convert_xrgb8888_case_desc(struct convert_xrgb8888_case *t,
|
||||
char *desc)
|
||||
{
|
||||
@ -293,8 +478,8 @@ static void drm_test_fb_xrgb8888_to_gray8(struct kunit *test)
|
||||
const struct convert_xrgb8888_case *params = test->param_value;
|
||||
const struct convert_to_gray8_result *result = ¶ms->gray8_result;
|
||||
size_t dst_size;
|
||||
__u8 *buf = NULL;
|
||||
__u32 *xrgb8888 = NULL;
|
||||
u8 *buf = NULL;
|
||||
__le32 *xrgb8888 = NULL;
|
||||
struct iosys_map dst, src;
|
||||
|
||||
struct drm_framebuffer fb = {
|
||||
@ -310,7 +495,7 @@ static void drm_test_fb_xrgb8888_to_gray8(struct kunit *test)
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
|
||||
iosys_map_set_vaddr(&dst, buf);
|
||||
|
||||
xrgb8888 = le32buf_to_cpu(test, params->xrgb8888, TEST_BUF_SIZE);
|
||||
xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
|
||||
iosys_map_set_vaddr(&src, xrgb8888);
|
||||
|
||||
@ -323,8 +508,8 @@ static void drm_test_fb_xrgb8888_to_rgb332(struct kunit *test)
|
||||
const struct convert_xrgb8888_case *params = test->param_value;
|
||||
const struct convert_to_rgb332_result *result = ¶ms->rgb332_result;
|
||||
size_t dst_size;
|
||||
__u8 *buf = NULL;
|
||||
__u32 *xrgb8888 = NULL;
|
||||
u8 *buf = NULL;
|
||||
__le32 *xrgb8888 = NULL;
|
||||
struct iosys_map dst, src;
|
||||
|
||||
struct drm_framebuffer fb = {
|
||||
@ -340,7 +525,7 @@ static void drm_test_fb_xrgb8888_to_rgb332(struct kunit *test)
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
|
||||
iosys_map_set_vaddr(&dst, buf);
|
||||
|
||||
xrgb8888 = le32buf_to_cpu(test, params->xrgb8888, TEST_BUF_SIZE);
|
||||
xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
|
||||
iosys_map_set_vaddr(&src, xrgb8888);
|
||||
|
||||
@ -353,8 +538,8 @@ static void drm_test_fb_xrgb8888_to_rgb565(struct kunit *test)
|
||||
const struct convert_xrgb8888_case *params = test->param_value;
|
||||
const struct convert_to_rgb565_result *result = ¶ms->rgb565_result;
|
||||
size_t dst_size;
|
||||
__u16 *buf = NULL;
|
||||
__u32 *xrgb8888 = NULL;
|
||||
u16 *buf = NULL;
|
||||
__le32 *xrgb8888 = NULL;
|
||||
struct iosys_map dst, src;
|
||||
|
||||
struct drm_framebuffer fb = {
|
||||
@ -370,24 +555,120 @@ static void drm_test_fb_xrgb8888_to_rgb565(struct kunit *test)
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
|
||||
iosys_map_set_vaddr(&dst, buf);
|
||||
|
||||
xrgb8888 = le32buf_to_cpu(test, params->xrgb8888, TEST_BUF_SIZE);
|
||||
xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
|
||||
iosys_map_set_vaddr(&src, xrgb8888);
|
||||
|
||||
drm_fb_xrgb8888_to_rgb565(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip, false);
|
||||
buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
|
||||
KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
|
||||
|
||||
buf = dst.vaddr; /* restore original value of buf */
|
||||
drm_fb_xrgb8888_to_rgb565(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip, true);
|
||||
buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
|
||||
KUNIT_EXPECT_MEMEQ(test, buf, result->expected_swab, dst_size);
|
||||
}
|
||||
|
||||
static void drm_test_fb_xrgb8888_to_xrgb1555(struct kunit *test)
|
||||
{
|
||||
const struct convert_xrgb8888_case *params = test->param_value;
|
||||
const struct convert_to_xrgb1555_result *result = ¶ms->xrgb1555_result;
|
||||
size_t dst_size;
|
||||
u16 *buf = NULL;
|
||||
__le32 *xrgb8888 = NULL;
|
||||
struct iosys_map dst, src;
|
||||
|
||||
struct drm_framebuffer fb = {
|
||||
.format = drm_format_info(DRM_FORMAT_XRGB8888),
|
||||
.pitches = { params->pitch, 0, 0 },
|
||||
};
|
||||
|
||||
dst_size = conversion_buf_size(DRM_FORMAT_XRGB1555, result->dst_pitch,
|
||||
¶ms->clip);
|
||||
KUNIT_ASSERT_GT(test, dst_size, 0);
|
||||
|
||||
buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
|
||||
iosys_map_set_vaddr(&dst, buf);
|
||||
|
||||
xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
|
||||
iosys_map_set_vaddr(&src, xrgb8888);
|
||||
|
||||
drm_fb_xrgb8888_to_xrgb1555(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip);
|
||||
buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
|
||||
KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0);
|
||||
}
|
||||
|
||||
static void drm_test_fb_xrgb8888_to_argb1555(struct kunit *test)
|
||||
{
|
||||
const struct convert_xrgb8888_case *params = test->param_value;
|
||||
const struct convert_to_argb1555_result *result = ¶ms->argb1555_result;
|
||||
size_t dst_size;
|
||||
u16 *buf = NULL;
|
||||
__le32 *xrgb8888 = NULL;
|
||||
struct iosys_map dst, src;
|
||||
|
||||
struct drm_framebuffer fb = {
|
||||
.format = drm_format_info(DRM_FORMAT_XRGB8888),
|
||||
.pitches = { params->pitch, 0, 0 },
|
||||
};
|
||||
|
||||
dst_size = conversion_buf_size(DRM_FORMAT_ARGB1555, result->dst_pitch,
|
||||
¶ms->clip);
|
||||
KUNIT_ASSERT_GT(test, dst_size, 0);
|
||||
|
||||
buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
|
||||
iosys_map_set_vaddr(&dst, buf);
|
||||
|
||||
xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
|
||||
iosys_map_set_vaddr(&src, xrgb8888);
|
||||
|
||||
drm_fb_xrgb8888_to_argb1555(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip);
|
||||
buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
|
||||
KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0);
|
||||
}
|
||||
|
||||
static void drm_test_fb_xrgb8888_to_rgba5551(struct kunit *test)
|
||||
{
|
||||
const struct convert_xrgb8888_case *params = test->param_value;
|
||||
const struct convert_to_rgba5551_result *result = ¶ms->rgba5551_result;
|
||||
size_t dst_size;
|
||||
u16 *buf = NULL;
|
||||
__le32 *xrgb8888 = NULL;
|
||||
struct iosys_map dst, src;
|
||||
|
||||
struct drm_framebuffer fb = {
|
||||
.format = drm_format_info(DRM_FORMAT_XRGB8888),
|
||||
.pitches = { params->pitch, 0, 0 },
|
||||
};
|
||||
|
||||
dst_size = conversion_buf_size(DRM_FORMAT_RGBA5551, result->dst_pitch,
|
||||
¶ms->clip);
|
||||
KUNIT_ASSERT_GT(test, dst_size, 0);
|
||||
|
||||
buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
|
||||
iosys_map_set_vaddr(&dst, buf);
|
||||
|
||||
xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
|
||||
iosys_map_set_vaddr(&src, xrgb8888);
|
||||
|
||||
drm_fb_xrgb8888_to_rgba5551(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip);
|
||||
buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
|
||||
KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0);
|
||||
}
|
||||
|
||||
static void drm_test_fb_xrgb8888_to_rgb888(struct kunit *test)
|
||||
{
|
||||
const struct convert_xrgb8888_case *params = test->param_value;
|
||||
const struct convert_to_rgb888_result *result = ¶ms->rgb888_result;
|
||||
size_t dst_size;
|
||||
__u8 *buf = NULL;
|
||||
__u32 *xrgb8888 = NULL;
|
||||
u8 *buf = NULL;
|
||||
__le32 *xrgb8888 = NULL;
|
||||
struct iosys_map dst, src;
|
||||
|
||||
struct drm_framebuffer fb = {
|
||||
@ -403,21 +684,56 @@ static void drm_test_fb_xrgb8888_to_rgb888(struct kunit *test)
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
|
||||
iosys_map_set_vaddr(&dst, buf);
|
||||
|
||||
xrgb8888 = le32buf_to_cpu(test, params->xrgb8888, TEST_BUF_SIZE);
|
||||
xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
|
||||
iosys_map_set_vaddr(&src, xrgb8888);
|
||||
|
||||
/*
|
||||
* RGB888 expected results are already in little-endian
|
||||
* order, so there's no need to convert the test output.
|
||||
*/
|
||||
drm_fb_xrgb8888_to_rgb888(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip);
|
||||
KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
|
||||
}
|
||||
|
||||
static void drm_test_fb_xrgb8888_to_argb8888(struct kunit *test)
|
||||
{
|
||||
const struct convert_xrgb8888_case *params = test->param_value;
|
||||
const struct convert_to_argb8888_result *result = ¶ms->argb8888_result;
|
||||
size_t dst_size;
|
||||
u32 *buf = NULL;
|
||||
__le32 *xrgb8888 = NULL;
|
||||
struct iosys_map dst, src;
|
||||
|
||||
struct drm_framebuffer fb = {
|
||||
.format = drm_format_info(DRM_FORMAT_XRGB8888),
|
||||
.pitches = { params->pitch, 0, 0 },
|
||||
};
|
||||
|
||||
dst_size = conversion_buf_size(DRM_FORMAT_ARGB8888,
|
||||
result->dst_pitch, ¶ms->clip);
|
||||
KUNIT_ASSERT_GT(test, dst_size, 0);
|
||||
|
||||
buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
|
||||
iosys_map_set_vaddr(&dst, buf);
|
||||
|
||||
xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
|
||||
iosys_map_set_vaddr(&src, xrgb8888);
|
||||
|
||||
drm_fb_xrgb8888_to_argb8888(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip);
|
||||
buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32));
|
||||
KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0);
|
||||
}
|
||||
|
||||
static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test)
|
||||
{
|
||||
const struct convert_xrgb8888_case *params = test->param_value;
|
||||
const struct convert_to_xrgb2101010_result *result = ¶ms->xrgb2101010_result;
|
||||
size_t dst_size;
|
||||
__u32 *buf = NULL;
|
||||
__u32 *xrgb8888 = NULL;
|
||||
u32 *buf = NULL;
|
||||
__le32 *xrgb8888 = NULL;
|
||||
struct iosys_map dst, src;
|
||||
|
||||
struct drm_framebuffer fb = {
|
||||
@ -433,7 +749,7 @@ static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test)
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
|
||||
iosys_map_set_vaddr(&dst, buf);
|
||||
|
||||
xrgb8888 = le32buf_to_cpu(test, params->xrgb8888, TEST_BUF_SIZE);
|
||||
xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
|
||||
iosys_map_set_vaddr(&src, xrgb8888);
|
||||
|
||||
@ -442,12 +758,48 @@ static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test)
|
||||
KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
|
||||
}
|
||||
|
||||
static void drm_test_fb_xrgb8888_to_argb2101010(struct kunit *test)
|
||||
{
|
||||
const struct convert_xrgb8888_case *params = test->param_value;
|
||||
const struct convert_to_argb2101010_result *result = ¶ms->argb2101010_result;
|
||||
size_t dst_size;
|
||||
u32 *buf = NULL;
|
||||
__le32 *xrgb8888 = NULL;
|
||||
struct iosys_map dst, src;
|
||||
|
||||
struct drm_framebuffer fb = {
|
||||
.format = drm_format_info(DRM_FORMAT_XRGB8888),
|
||||
.pitches = { params->pitch, 0, 0 },
|
||||
};
|
||||
|
||||
dst_size = conversion_buf_size(DRM_FORMAT_ARGB2101010,
|
||||
result->dst_pitch, ¶ms->clip);
|
||||
KUNIT_ASSERT_GT(test, dst_size, 0);
|
||||
|
||||
buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
|
||||
iosys_map_set_vaddr(&dst, buf);
|
||||
|
||||
xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
|
||||
iosys_map_set_vaddr(&src, xrgb8888);
|
||||
|
||||
drm_fb_xrgb8888_to_argb2101010(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip);
|
||||
buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32));
|
||||
KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0);
|
||||
}
|
||||
|
||||
static struct kunit_case drm_format_helper_test_cases[] = {
|
||||
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_gray8, convert_xrgb8888_gen_params),
|
||||
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb332, convert_xrgb8888_gen_params),
|
||||
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb565, convert_xrgb8888_gen_params),
|
||||
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_xrgb1555, convert_xrgb8888_gen_params),
|
||||
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb1555, convert_xrgb8888_gen_params),
|
||||
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgba5551, convert_xrgb8888_gen_params),
|
||||
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb888, convert_xrgb8888_gen_params),
|
||||
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb8888, convert_xrgb8888_gen_params),
|
||||
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_xrgb2101010, convert_xrgb8888_gen_params),
|
||||
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb2101010, convert_xrgb8888_gen_params),
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -754,24 +754,6 @@ static void ofdrm_crtc_state_destroy(struct ofdrm_crtc_state *ofdrm_crtc_state)
|
||||
kfree(ofdrm_crtc_state);
|
||||
}
|
||||
|
||||
/*
|
||||
* Support all formats of OF display and maybe more; in order
|
||||
* of preference. The display's update function will do any
|
||||
* conversion necessary.
|
||||
*
|
||||
* TODO: Add blit helpers for remaining formats and uncomment
|
||||
* constants.
|
||||
*/
|
||||
static const uint32_t ofdrm_primary_plane_formats[] = {
|
||||
DRM_FORMAT_XRGB8888,
|
||||
DRM_FORMAT_RGB565,
|
||||
//DRM_FORMAT_XRGB1555,
|
||||
//DRM_FORMAT_C8,
|
||||
/* Big-endian formats below */
|
||||
DRM_FORMAT_BGRX8888,
|
||||
DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN,
|
||||
};
|
||||
|
||||
static const uint64_t ofdrm_primary_plane_format_modifiers[] = {
|
||||
DRM_FORMAT_MOD_LINEAR,
|
||||
DRM_FORMAT_MOD_INVALID
|
||||
@ -1290,8 +1272,6 @@ static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv,
|
||||
/* Primary plane */
|
||||
|
||||
nformats = drm_fb_build_fourcc_list(dev, &format->format, 1,
|
||||
ofdrm_primary_plane_formats,
|
||||
ARRAY_SIZE(ofdrm_primary_plane_formats),
|
||||
odev->formats, ARRAY_SIZE(odev->formats));
|
||||
|
||||
primary_plane = &odev->primary_plane;
|
||||
@ -1372,6 +1352,7 @@ static int ofdrm_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct ofdrm_device *odev;
|
||||
struct drm_device *dev;
|
||||
unsigned int color_mode;
|
||||
int ret;
|
||||
|
||||
odev = ofdrm_device_create(&ofdrm_driver, pdev);
|
||||
@ -1383,7 +1364,11 @@ static int ofdrm_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_fbdev_generic_setup(dev, drm_format_info_bpp(odev->format, 0));
|
||||
color_mode = drm_format_info_bpp(odev->format, 0);
|
||||
if (color_mode == 16)
|
||||
color_mode = odev->format->depth; // can be 15 or 16
|
||||
|
||||
drm_fbdev_generic_setup(dev, color_mode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -446,25 +446,6 @@ static int simpledrm_device_init_regulators(struct simpledrm_device *sdev)
|
||||
* Modesetting
|
||||
*/
|
||||
|
||||
/*
|
||||
* Support all formats of simplefb and maybe more; in order
|
||||
* of preference. The display's update function will do any
|
||||
* conversion necessary.
|
||||
*
|
||||
* TODO: Add blit helpers for remaining formats and uncomment
|
||||
* constants.
|
||||
*/
|
||||
static const uint32_t simpledrm_primary_plane_formats[] = {
|
||||
DRM_FORMAT_XRGB8888,
|
||||
DRM_FORMAT_ARGB8888,
|
||||
DRM_FORMAT_RGB565,
|
||||
//DRM_FORMAT_XRGB1555,
|
||||
//DRM_FORMAT_ARGB1555,
|
||||
DRM_FORMAT_RGB888,
|
||||
DRM_FORMAT_XRGB2101010,
|
||||
DRM_FORMAT_ARGB2101010,
|
||||
};
|
||||
|
||||
static const uint64_t simpledrm_primary_plane_format_modifiers[] = {
|
||||
DRM_FORMAT_MOD_LINEAR,
|
||||
DRM_FORMAT_MOD_INVALID
|
||||
@ -745,8 +726,6 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv,
|
||||
/* Primary plane */
|
||||
|
||||
nformats = drm_fb_build_fourcc_list(dev, &format->format, 1,
|
||||
simpledrm_primary_plane_formats,
|
||||
ARRAY_SIZE(simpledrm_primary_plane_formats),
|
||||
sdev->formats, ARRAY_SIZE(sdev->formats));
|
||||
|
||||
primary_plane = &sdev->primary_plane;
|
||||
@ -823,6 +802,7 @@ static int simpledrm_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct simpledrm_device *sdev;
|
||||
struct drm_device *dev;
|
||||
unsigned int color_mode;
|
||||
int ret;
|
||||
|
||||
sdev = simpledrm_device_create(&simpledrm_driver, pdev);
|
||||
@ -834,7 +814,11 @@ static int simpledrm_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_fbdev_generic_setup(dev, drm_format_info_bpp(sdev->format, 0));
|
||||
color_mode = drm_format_info_bpp(sdev->format, 0);
|
||||
if (color_mode == 16)
|
||||
color_mode = sdev->format->depth; // can be 15 or 16
|
||||
|
||||
drm_fbdev_generic_setup(dev, color_mode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -861,7 +861,6 @@ v3d_submit_tfu_ioctl(struct drm_device *dev, void *data,
|
||||
|
||||
job->args = *args;
|
||||
|
||||
spin_lock(&file_priv->table_lock);
|
||||
for (job->base.bo_count = 0;
|
||||
job->base.bo_count < ARRAY_SIZE(args->bo_handles);
|
||||
job->base.bo_count++) {
|
||||
@ -870,20 +869,16 @@ v3d_submit_tfu_ioctl(struct drm_device *dev, void *data,
|
||||
if (!args->bo_handles[job->base.bo_count])
|
||||
break;
|
||||
|
||||
bo = idr_find(&file_priv->object_idr,
|
||||
args->bo_handles[job->base.bo_count]);
|
||||
bo = drm_gem_object_lookup(file_priv, args->bo_handles[job->base.bo_count]);
|
||||
if (!bo) {
|
||||
DRM_DEBUG("Failed to look up GEM BO %d: %d\n",
|
||||
job->base.bo_count,
|
||||
args->bo_handles[job->base.bo_count]);
|
||||
ret = -ENOENT;
|
||||
spin_unlock(&file_priv->table_lock);
|
||||
goto fail;
|
||||
}
|
||||
drm_gem_object_get(bo);
|
||||
job->base.bo[job->base.bo_count] = bo;
|
||||
}
|
||||
spin_unlock(&file_priv->table_lock);
|
||||
|
||||
ret = v3d_lock_bo_reservations(&job->base, &acquire_ctx);
|
||||
if (ret)
|
||||
|
@ -335,8 +335,14 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encode
|
||||
bool is_dsi = (vc4_encoder->type == VC4_ENCODER_TYPE_DSI0 ||
|
||||
vc4_encoder->type == VC4_ENCODER_TYPE_DSI1);
|
||||
bool is_dsi1 = vc4_encoder->type == VC4_ENCODER_TYPE_DSI1;
|
||||
bool is_vec = vc4_encoder->type == VC4_ENCODER_TYPE_VEC;
|
||||
u32 format = is_dsi1 ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24;
|
||||
u8 ppc = pv_data->pixels_per_clock;
|
||||
|
||||
u16 vert_bp = mode->crtc_vtotal - mode->crtc_vsync_end;
|
||||
u16 vert_sync = mode->crtc_vsync_end - mode->crtc_vsync_start;
|
||||
u16 vert_fp = mode->crtc_vsync_start - mode->crtc_vdisplay;
|
||||
|
||||
bool debug_dump_regs = false;
|
||||
int idx;
|
||||
|
||||
@ -364,49 +370,60 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encode
|
||||
VC4_SET_FIELD(mode->hdisplay * pixel_rep / ppc,
|
||||
PV_HORZB_HACTIVE));
|
||||
|
||||
CRTC_WRITE(PV_VERTA,
|
||||
VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end +
|
||||
interlace,
|
||||
PV_VERTA_VBP) |
|
||||
VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start,
|
||||
PV_VERTA_VSYNC));
|
||||
CRTC_WRITE(PV_VERTB,
|
||||
VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay,
|
||||
PV_VERTB_VFP) |
|
||||
VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE));
|
||||
|
||||
if (interlace) {
|
||||
bool odd_field_first = false;
|
||||
u32 field_delay = mode->htotal * pixel_rep / (2 * ppc);
|
||||
u16 vert_bp_even = vert_bp;
|
||||
u16 vert_fp_even = vert_fp;
|
||||
|
||||
if (is_vec) {
|
||||
/* VEC (composite output) */
|
||||
++field_delay;
|
||||
if (mode->htotal == 858) {
|
||||
/* 525-line mode (NTSC or PAL-M) */
|
||||
odd_field_first = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (odd_field_first)
|
||||
++vert_fp_even;
|
||||
else
|
||||
++vert_bp;
|
||||
|
||||
CRTC_WRITE(PV_VERTA_EVEN,
|
||||
VC4_SET_FIELD(mode->crtc_vtotal -
|
||||
mode->crtc_vsync_end,
|
||||
PV_VERTA_VBP) |
|
||||
VC4_SET_FIELD(mode->crtc_vsync_end -
|
||||
mode->crtc_vsync_start,
|
||||
PV_VERTA_VSYNC));
|
||||
VC4_SET_FIELD(vert_bp_even, PV_VERTA_VBP) |
|
||||
VC4_SET_FIELD(vert_sync, PV_VERTA_VSYNC));
|
||||
CRTC_WRITE(PV_VERTB_EVEN,
|
||||
VC4_SET_FIELD(mode->crtc_vsync_start -
|
||||
mode->crtc_vdisplay,
|
||||
PV_VERTB_VFP) |
|
||||
VC4_SET_FIELD(vert_fp_even, PV_VERTB_VFP) |
|
||||
VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE));
|
||||
|
||||
/* We set up first field even mode for HDMI. VEC's
|
||||
* NTSC mode would want first field odd instead, once
|
||||
* we support it (to do so, set ODD_FIRST and put the
|
||||
* delay in VSYNCD_EVEN instead).
|
||||
/* We set up first field even mode for HDMI and VEC's PAL.
|
||||
* For NTSC, we need first field odd.
|
||||
*/
|
||||
CRTC_WRITE(PV_V_CONTROL,
|
||||
PV_VCONTROL_CONTINUOUS |
|
||||
(is_dsi ? PV_VCONTROL_DSI : 0) |
|
||||
PV_VCONTROL_INTERLACE |
|
||||
VC4_SET_FIELD(mode->htotal * pixel_rep / (2 * ppc),
|
||||
PV_VCONTROL_ODD_DELAY));
|
||||
CRTC_WRITE(PV_VSYNCD_EVEN, 0);
|
||||
(odd_field_first
|
||||
? PV_VCONTROL_ODD_FIRST
|
||||
: VC4_SET_FIELD(field_delay,
|
||||
PV_VCONTROL_ODD_DELAY)));
|
||||
CRTC_WRITE(PV_VSYNCD_EVEN,
|
||||
(odd_field_first ? field_delay : 0));
|
||||
} else {
|
||||
CRTC_WRITE(PV_V_CONTROL,
|
||||
PV_VCONTROL_CONTINUOUS |
|
||||
(is_dsi ? PV_VCONTROL_DSI : 0));
|
||||
CRTC_WRITE(PV_VSYNCD_EVEN, 0);
|
||||
}
|
||||
|
||||
CRTC_WRITE(PV_VERTA,
|
||||
VC4_SET_FIELD(vert_bp, PV_VERTA_VBP) |
|
||||
VC4_SET_FIELD(vert_sync, PV_VERTA_VSYNC));
|
||||
CRTC_WRITE(PV_VERTB,
|
||||
VC4_SET_FIELD(vert_fp, PV_VERTB_VFP) |
|
||||
VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE));
|
||||
|
||||
if (is_dsi)
|
||||
CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);
|
||||
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include <linux/component.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
@ -1307,11 +1307,12 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
|
||||
VC4_SET_FIELD(mode->crtc_vdisplay, VC5_HDMI_VERTA_VAL));
|
||||
u32 vertb = (VC4_SET_FIELD(mode->htotal >> (2 - pixel_rep),
|
||||
VC5_HDMI_VERTB_VSPO) |
|
||||
VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end,
|
||||
VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end +
|
||||
interlaced,
|
||||
VC4_HDMI_VERTB_VBP));
|
||||
u32 vertb_even = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) |
|
||||
VC4_SET_FIELD(mode->crtc_vtotal -
|
||||
mode->crtc_vsync_end - interlaced,
|
||||
mode->crtc_vsync_end,
|
||||
VC4_HDMI_VERTB_VBP));
|
||||
unsigned long flags;
|
||||
unsigned char gcp;
|
||||
|
@ -370,28 +370,30 @@ static int vc4_hvs_init_channel(struct vc4_hvs *hvs, struct drm_crtc *crtc,
|
||||
* mode.
|
||||
*/
|
||||
dispctrl = SCALER_DISPCTRLX_ENABLE;
|
||||
dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(chan));
|
||||
|
||||
if (!vc4->is_vc5)
|
||||
if (!vc4->is_vc5) {
|
||||
dispctrl |= VC4_SET_FIELD(mode->hdisplay,
|
||||
SCALER_DISPCTRLX_WIDTH) |
|
||||
VC4_SET_FIELD(mode->vdisplay,
|
||||
SCALER_DISPCTRLX_HEIGHT) |
|
||||
(oneshot ? SCALER_DISPCTRLX_ONESHOT : 0);
|
||||
else
|
||||
dispbkgndx |= SCALER_DISPBKGND_AUTOHS;
|
||||
} else {
|
||||
dispctrl |= VC4_SET_FIELD(mode->hdisplay,
|
||||
SCALER5_DISPCTRLX_WIDTH) |
|
||||
VC4_SET_FIELD(mode->vdisplay,
|
||||
SCALER5_DISPCTRLX_HEIGHT) |
|
||||
(oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
|
||||
dispbkgndx &= ~SCALER5_DISPBKGND_BCK2BCK;
|
||||
}
|
||||
|
||||
HVS_WRITE(SCALER_DISPCTRLX(chan), dispctrl);
|
||||
|
||||
dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(chan));
|
||||
dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
|
||||
dispbkgndx &= ~SCALER_DISPBKGND_INTERLACE;
|
||||
|
||||
HVS_WRITE(SCALER_DISPBKGNDX(chan), dispbkgndx |
|
||||
SCALER_DISPBKGND_AUTOHS |
|
||||
((!vc4->is_vc5) ? SCALER_DISPBKGND_GAMMA : 0) |
|
||||
(interlace ? SCALER_DISPBKGND_INTERLACE : 0));
|
||||
|
||||
@ -568,6 +570,8 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
|
||||
bool enable_bg_fill = false;
|
||||
u32 __iomem *dlist_start = vc4->hvs->dlist + vc4_state->mm.start;
|
||||
u32 __iomem *dlist_next = dlist_start;
|
||||
unsigned int zpos = 0;
|
||||
bool found = false;
|
||||
int idx;
|
||||
|
||||
if (!drm_dev_enter(dev, &idx)) {
|
||||
@ -575,29 +579,43 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
|
||||
return;
|
||||
}
|
||||
|
||||
if (vc4_state->assigned_channel == VC4_HVS_CHANNEL_DISABLED)
|
||||
return;
|
||||
|
||||
if (debug_dump_regs) {
|
||||
DRM_INFO("CRTC %d HVS before:\n", drm_crtc_index(crtc));
|
||||
vc4_hvs_dump_state(hvs);
|
||||
}
|
||||
|
||||
/* Copy all the active planes' dlist contents to the hardware dlist. */
|
||||
drm_atomic_crtc_for_each_plane(plane, crtc) {
|
||||
/* Is this the first active plane? */
|
||||
if (dlist_next == dlist_start) {
|
||||
/* We need to enable background fill when a plane
|
||||
* could be alpha blending from the background, i.e.
|
||||
* where no other plane is underneath. It suffices to
|
||||
* consider the first active plane here since we set
|
||||
* needs_bg_fill such that either the first plane
|
||||
* already needs it or all planes on top blend from
|
||||
* the first or a lower plane.
|
||||
*/
|
||||
vc4_plane_state = to_vc4_plane_state(plane->state);
|
||||
enable_bg_fill = vc4_plane_state->needs_bg_fill;
|
||||
do {
|
||||
found = false;
|
||||
|
||||
drm_atomic_crtc_for_each_plane(plane, crtc) {
|
||||
if (plane->state->normalized_zpos != zpos)
|
||||
continue;
|
||||
|
||||
/* Is this the first active plane? */
|
||||
if (dlist_next == dlist_start) {
|
||||
/* We need to enable background fill when a plane
|
||||
* could be alpha blending from the background, i.e.
|
||||
* where no other plane is underneath. It suffices to
|
||||
* consider the first active plane here since we set
|
||||
* needs_bg_fill such that either the first plane
|
||||
* already needs it or all planes on top blend from
|
||||
* the first or a lower plane.
|
||||
*/
|
||||
vc4_plane_state = to_vc4_plane_state(plane->state);
|
||||
enable_bg_fill = vc4_plane_state->needs_bg_fill;
|
||||
}
|
||||
|
||||
dlist_next += vc4_plane_write_dlist(plane, dlist_next);
|
||||
|
||||
found = true;
|
||||
}
|
||||
|
||||
dlist_next += vc4_plane_write_dlist(plane, dlist_next);
|
||||
}
|
||||
zpos++;
|
||||
} while (found);
|
||||
|
||||
writel(SCALER_CTL0_END, dlist_next);
|
||||
dlist_next++;
|
||||
@ -658,7 +676,8 @@ void vc4_hvs_mask_underrun(struct vc4_hvs *hvs, int channel)
|
||||
return;
|
||||
|
||||
dispctrl = HVS_READ(SCALER_DISPCTRL);
|
||||
dispctrl &= ~SCALER_DISPCTRL_DSPEISLUR(channel);
|
||||
dispctrl &= ~(hvs->vc4->is_vc5 ? SCALER5_DISPCTRL_DSPEISLUR(channel) :
|
||||
SCALER_DISPCTRL_DSPEISLUR(channel));
|
||||
|
||||
HVS_WRITE(SCALER_DISPCTRL, dispctrl);
|
||||
|
||||
@ -675,7 +694,8 @@ void vc4_hvs_unmask_underrun(struct vc4_hvs *hvs, int channel)
|
||||
return;
|
||||
|
||||
dispctrl = HVS_READ(SCALER_DISPCTRL);
|
||||
dispctrl |= SCALER_DISPCTRL_DSPEISLUR(channel);
|
||||
dispctrl |= (hvs->vc4->is_vc5 ? SCALER5_DISPCTRL_DSPEISLUR(channel) :
|
||||
SCALER_DISPCTRL_DSPEISLUR(channel));
|
||||
|
||||
HVS_WRITE(SCALER_DISPSTAT,
|
||||
SCALER_DISPSTAT_EUFLOW(channel));
|
||||
@ -701,6 +721,7 @@ static irqreturn_t vc4_hvs_irq_handler(int irq, void *data)
|
||||
int channel;
|
||||
u32 control;
|
||||
u32 status;
|
||||
u32 dspeislur;
|
||||
|
||||
/*
|
||||
* NOTE: We don't need to protect the register access using
|
||||
@ -717,9 +738,11 @@ static irqreturn_t vc4_hvs_irq_handler(int irq, void *data)
|
||||
control = HVS_READ(SCALER_DISPCTRL);
|
||||
|
||||
for (channel = 0; channel < SCALER_CHANNELS_COUNT; channel++) {
|
||||
dspeislur = vc4->is_vc5 ? SCALER5_DISPCTRL_DSPEISLUR(channel) :
|
||||
SCALER_DISPCTRL_DSPEISLUR(channel);
|
||||
/* Interrupt masking is not always honored, so check it here. */
|
||||
if (status & SCALER_DISPSTAT_EUFLOW(channel) &&
|
||||
control & SCALER_DISPCTRL_DSPEISLUR(channel)) {
|
||||
control & dspeislur) {
|
||||
vc4_hvs_mask_underrun(hvs, channel);
|
||||
vc4_hvs_report_underrun(dev);
|
||||
|
||||
@ -806,7 +829,7 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
|
||||
struct vc4_hvs *hvs = NULL;
|
||||
int ret;
|
||||
u32 dispctrl;
|
||||
u32 reg;
|
||||
u32 reg, top;
|
||||
|
||||
hvs = __vc4_hvs_alloc(vc4, NULL);
|
||||
if (IS_ERR(hvs))
|
||||
@ -899,22 +922,102 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
|
||||
SCALER_DISPCTRL_DISPEIRQ(1) |
|
||||
SCALER_DISPCTRL_DISPEIRQ(2);
|
||||
|
||||
dispctrl &= ~(SCALER_DISPCTRL_DMAEIRQ |
|
||||
SCALER_DISPCTRL_SLVWREIRQ |
|
||||
SCALER_DISPCTRL_SLVRDEIRQ |
|
||||
SCALER_DISPCTRL_DSPEIEOF(0) |
|
||||
SCALER_DISPCTRL_DSPEIEOF(1) |
|
||||
SCALER_DISPCTRL_DSPEIEOF(2) |
|
||||
SCALER_DISPCTRL_DSPEIEOLN(0) |
|
||||
SCALER_DISPCTRL_DSPEIEOLN(1) |
|
||||
SCALER_DISPCTRL_DSPEIEOLN(2) |
|
||||
SCALER_DISPCTRL_DSPEISLUR(0) |
|
||||
SCALER_DISPCTRL_DSPEISLUR(1) |
|
||||
SCALER_DISPCTRL_DSPEISLUR(2) |
|
||||
SCALER_DISPCTRL_SCLEIRQ);
|
||||
if (!vc4->is_vc5)
|
||||
dispctrl &= ~(SCALER_DISPCTRL_DMAEIRQ |
|
||||
SCALER_DISPCTRL_SLVWREIRQ |
|
||||
SCALER_DISPCTRL_SLVRDEIRQ |
|
||||
SCALER_DISPCTRL_DSPEIEOF(0) |
|
||||
SCALER_DISPCTRL_DSPEIEOF(1) |
|
||||
SCALER_DISPCTRL_DSPEIEOF(2) |
|
||||
SCALER_DISPCTRL_DSPEIEOLN(0) |
|
||||
SCALER_DISPCTRL_DSPEIEOLN(1) |
|
||||
SCALER_DISPCTRL_DSPEIEOLN(2) |
|
||||
SCALER_DISPCTRL_DSPEISLUR(0) |
|
||||
SCALER_DISPCTRL_DSPEISLUR(1) |
|
||||
SCALER_DISPCTRL_DSPEISLUR(2) |
|
||||
SCALER_DISPCTRL_SCLEIRQ);
|
||||
else
|
||||
dispctrl &= ~(SCALER_DISPCTRL_DMAEIRQ |
|
||||
SCALER5_DISPCTRL_SLVEIRQ |
|
||||
SCALER5_DISPCTRL_DSPEIEOF(0) |
|
||||
SCALER5_DISPCTRL_DSPEIEOF(1) |
|
||||
SCALER5_DISPCTRL_DSPEIEOF(2) |
|
||||
SCALER5_DISPCTRL_DSPEIEOLN(0) |
|
||||
SCALER5_DISPCTRL_DSPEIEOLN(1) |
|
||||
SCALER5_DISPCTRL_DSPEIEOLN(2) |
|
||||
SCALER5_DISPCTRL_DSPEISLUR(0) |
|
||||
SCALER5_DISPCTRL_DSPEISLUR(1) |
|
||||
SCALER5_DISPCTRL_DSPEISLUR(2) |
|
||||
SCALER_DISPCTRL_SCLEIRQ);
|
||||
|
||||
|
||||
/* Set AXI panic mode.
|
||||
* VC4 panics when < 2 lines in FIFO.
|
||||
* VC5 panics when less than 1 line in the FIFO.
|
||||
*/
|
||||
dispctrl &= ~(SCALER_DISPCTRL_PANIC0_MASK |
|
||||
SCALER_DISPCTRL_PANIC1_MASK |
|
||||
SCALER_DISPCTRL_PANIC2_MASK);
|
||||
dispctrl |= VC4_SET_FIELD(2, SCALER_DISPCTRL_PANIC0);
|
||||
dispctrl |= VC4_SET_FIELD(2, SCALER_DISPCTRL_PANIC1);
|
||||
dispctrl |= VC4_SET_FIELD(2, SCALER_DISPCTRL_PANIC2);
|
||||
|
||||
HVS_WRITE(SCALER_DISPCTRL, dispctrl);
|
||||
|
||||
/* Recompute Composite Output Buffer (COB) allocations for the displays
|
||||
*/
|
||||
if (!vc4->is_vc5) {
|
||||
/* The COB is 20736 pixels, or just over 10 lines at 2048 wide.
|
||||
* The bottom 2048 pixels are full 32bpp RGBA (intended for the
|
||||
* TXP composing RGBA to memory), whilst the remainder are only
|
||||
* 24bpp RGB.
|
||||
*
|
||||
* Assign 3 lines to channels 1 & 2, and just over 4 lines to
|
||||
* channel 0.
|
||||
*/
|
||||
#define VC4_COB_SIZE 20736
|
||||
#define VC4_COB_LINE_WIDTH 2048
|
||||
#define VC4_COB_NUM_LINES 3
|
||||
reg = 0;
|
||||
top = VC4_COB_LINE_WIDTH * VC4_COB_NUM_LINES;
|
||||
reg |= (top - 1) << 16;
|
||||
HVS_WRITE(SCALER_DISPBASE2, reg);
|
||||
reg = top;
|
||||
top += VC4_COB_LINE_WIDTH * VC4_COB_NUM_LINES;
|
||||
reg |= (top - 1) << 16;
|
||||
HVS_WRITE(SCALER_DISPBASE1, reg);
|
||||
reg = top;
|
||||
top = VC4_COB_SIZE;
|
||||
reg |= (top - 1) << 16;
|
||||
HVS_WRITE(SCALER_DISPBASE0, reg);
|
||||
} else {
|
||||
/* The COB is 44416 pixels, or 10.8 lines at 4096 wide.
|
||||
* The bottom 4096 pixels are full RGBA (intended for the TXP
|
||||
* composing RGBA to memory), whilst the remainder are only
|
||||
* RGB. Addressing is always pixel wide.
|
||||
*
|
||||
* Assign 3 lines of 4096 to channels 1 & 2, and just over 4
|
||||
* lines. to channel 0.
|
||||
*/
|
||||
#define VC5_COB_SIZE 44416
|
||||
#define VC5_COB_LINE_WIDTH 4096
|
||||
#define VC5_COB_NUM_LINES 3
|
||||
reg = 0;
|
||||
top = VC5_COB_LINE_WIDTH * VC5_COB_NUM_LINES;
|
||||
reg |= top << 16;
|
||||
HVS_WRITE(SCALER_DISPBASE2, reg);
|
||||
top += 16;
|
||||
reg = top;
|
||||
top += VC5_COB_LINE_WIDTH * VC5_COB_NUM_LINES;
|
||||
reg |= top << 16;
|
||||
HVS_WRITE(SCALER_DISPBASE1, reg);
|
||||
top += 16;
|
||||
reg = top;
|
||||
top = VC5_COB_SIZE;
|
||||
reg |= top << 16;
|
||||
HVS_WRITE(SCALER_DISPBASE0, reg);
|
||||
}
|
||||
|
||||
ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
|
||||
vc4_hvs_irq_handler, 0, "vc4 hvs", drm);
|
||||
if (ret)
|
||||
|
@ -1074,6 +1074,7 @@ int vc4_kms_load(struct drm_device *dev)
|
||||
dev->mode_config.helper_private = &vc4_mode_config_helpers;
|
||||
dev->mode_config.preferred_depth = 24;
|
||||
dev->mode_config.async_page_flip = true;
|
||||
dev->mode_config.normalize_zpos = true;
|
||||
|
||||
ret = vc4_ctm_obj_init(vc4);
|
||||
if (ret)
|
||||
|
@ -65,78 +65,176 @@ static const struct hvs_format {
|
||||
.drm = DRM_FORMAT_RGB565,
|
||||
.hvs = HVS_PIXEL_FORMAT_RGB565,
|
||||
.pixel_order = HVS_PIXEL_ORDER_XRGB,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_XRGB,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_BGR565,
|
||||
.hvs = HVS_PIXEL_FORMAT_RGB565,
|
||||
.pixel_order = HVS_PIXEL_ORDER_XBGR,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_XBGR,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_ARGB1555,
|
||||
.hvs = HVS_PIXEL_FORMAT_RGBA5551,
|
||||
.pixel_order = HVS_PIXEL_ORDER_ABGR,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_XRGB1555,
|
||||
.hvs = HVS_PIXEL_FORMAT_RGBA5551,
|
||||
.pixel_order = HVS_PIXEL_ORDER_ABGR,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_RGB888,
|
||||
.hvs = HVS_PIXEL_FORMAT_RGB888,
|
||||
.pixel_order = HVS_PIXEL_ORDER_XRGB,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_XRGB,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_BGR888,
|
||||
.hvs = HVS_PIXEL_FORMAT_RGB888,
|
||||
.pixel_order = HVS_PIXEL_ORDER_XBGR,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_XBGR,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_YUV422,
|
||||
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE,
|
||||
.pixel_order = HVS_PIXEL_ORDER_XYCBCR,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCBCR,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_YVU422,
|
||||
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE,
|
||||
.pixel_order = HVS_PIXEL_ORDER_XYCRCB,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCRCB,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_YUV420,
|
||||
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE,
|
||||
.pixel_order = HVS_PIXEL_ORDER_XYCBCR,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCBCR,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_YVU420,
|
||||
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE,
|
||||
.pixel_order = HVS_PIXEL_ORDER_XYCRCB,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCRCB,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_NV12,
|
||||
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE,
|
||||
.pixel_order = HVS_PIXEL_ORDER_XYCBCR,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCBCR,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_NV21,
|
||||
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE,
|
||||
.pixel_order = HVS_PIXEL_ORDER_XYCRCB,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCRCB,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_NV16,
|
||||
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE,
|
||||
.pixel_order = HVS_PIXEL_ORDER_XYCBCR,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCBCR,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_NV61,
|
||||
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE,
|
||||
.pixel_order = HVS_PIXEL_ORDER_XYCRCB,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCRCB,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_P030,
|
||||
.hvs = HVS_PIXEL_FORMAT_YCBCR_10BIT,
|
||||
.pixel_order = HVS_PIXEL_ORDER_XYCBCR,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCBCR,
|
||||
.hvs5_only = true,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_XRGB2101010,
|
||||
.hvs = HVS_PIXEL_FORMAT_RGBA1010102,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
|
||||
.hvs5_only = true,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_ARGB2101010,
|
||||
.hvs = HVS_PIXEL_FORMAT_RGBA1010102,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
|
||||
.hvs5_only = true,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_ABGR2101010,
|
||||
.hvs = HVS_PIXEL_FORMAT_RGBA1010102,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR,
|
||||
.hvs5_only = true,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_XBGR2101010,
|
||||
.hvs = HVS_PIXEL_FORMAT_RGBA1010102,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR,
|
||||
.hvs5_only = true,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_RGB332,
|
||||
.hvs = HVS_PIXEL_FORMAT_RGB332,
|
||||
.pixel_order = HVS_PIXEL_ORDER_ARGB,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_BGR233,
|
||||
.hvs = HVS_PIXEL_FORMAT_RGB332,
|
||||
.pixel_order = HVS_PIXEL_ORDER_ABGR,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_XRGB4444,
|
||||
.hvs = HVS_PIXEL_FORMAT_RGBA4444,
|
||||
.pixel_order = HVS_PIXEL_ORDER_ABGR,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_ARGB4444,
|
||||
.hvs = HVS_PIXEL_FORMAT_RGBA4444,
|
||||
.pixel_order = HVS_PIXEL_ORDER_ABGR,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_XBGR4444,
|
||||
.hvs = HVS_PIXEL_FORMAT_RGBA4444,
|
||||
.pixel_order = HVS_PIXEL_ORDER_ARGB,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_ABGR4444,
|
||||
.hvs = HVS_PIXEL_FORMAT_RGBA4444,
|
||||
.pixel_order = HVS_PIXEL_ORDER_ARGB,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_BGRX4444,
|
||||
.hvs = HVS_PIXEL_FORMAT_RGBA4444,
|
||||
.pixel_order = HVS_PIXEL_ORDER_RGBA,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_BGRA,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_BGRA4444,
|
||||
.hvs = HVS_PIXEL_FORMAT_RGBA4444,
|
||||
.pixel_order = HVS_PIXEL_ORDER_RGBA,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_BGRA,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_RGBX4444,
|
||||
.hvs = HVS_PIXEL_FORMAT_RGBA4444,
|
||||
.pixel_order = HVS_PIXEL_ORDER_BGRA,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_RGBA,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_RGBA4444,
|
||||
.hvs = HVS_PIXEL_FORMAT_RGBA4444,
|
||||
.pixel_order = HVS_PIXEL_ORDER_BGRA,
|
||||
.pixel_order_hvs5 = HVS_PIXEL_ORDER_RGBA,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct hvs_format *vc4_get_hvs_format(u32 drm_format)
|
||||
@ -1001,15 +1099,10 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
|
||||
vc4_dlist_write(vc4_state, 0xc0c0c0c0);
|
||||
|
||||
} else {
|
||||
u32 hvs_pixel_order = format->pixel_order;
|
||||
|
||||
if (format->pixel_order_hvs5)
|
||||
hvs_pixel_order = format->pixel_order_hvs5;
|
||||
|
||||
/* Control word */
|
||||
vc4_dlist_write(vc4_state,
|
||||
SCALER_CTL0_VALID |
|
||||
(hvs_pixel_order << SCALER_CTL0_ORDER_SHIFT) |
|
||||
(format->pixel_order_hvs5 << SCALER_CTL0_ORDER_SHIFT) |
|
||||
(hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) |
|
||||
VC4_SET_FIELD(tiling, SCALER_CTL0_TILING) |
|
||||
(vc4_state->is_unity ?
|
||||
@ -1488,6 +1581,16 @@ static bool vc4_format_mod_supported(struct drm_plane *plane,
|
||||
case DRM_FORMAT_BGRX1010102:
|
||||
case DRM_FORMAT_RGBA1010102:
|
||||
case DRM_FORMAT_BGRA1010102:
|
||||
case DRM_FORMAT_XRGB4444:
|
||||
case DRM_FORMAT_ARGB4444:
|
||||
case DRM_FORMAT_XBGR4444:
|
||||
case DRM_FORMAT_ABGR4444:
|
||||
case DRM_FORMAT_RGBX4444:
|
||||
case DRM_FORMAT_RGBA4444:
|
||||
case DRM_FORMAT_BGRX4444:
|
||||
case DRM_FORMAT_BGRA4444:
|
||||
case DRM_FORMAT_RGB332:
|
||||
case DRM_FORMAT_BGR233:
|
||||
case DRM_FORMAT_YUV422:
|
||||
case DRM_FORMAT_YVU422:
|
||||
case DRM_FORMAT_YUV420:
|
||||
@ -1568,9 +1671,14 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
|
||||
DRM_COLOR_YCBCR_BT709,
|
||||
DRM_COLOR_YCBCR_LIMITED_RANGE);
|
||||
|
||||
if (type == DRM_PLANE_TYPE_PRIMARY)
|
||||
drm_plane_create_zpos_immutable_property(plane, 0);
|
||||
|
||||
return plane;
|
||||
}
|
||||
|
||||
#define VC4_NUM_OVERLAY_PLANES 16
|
||||
|
||||
int vc4_plane_create_additional_planes(struct drm_device *drm)
|
||||
{
|
||||
struct drm_plane *cursor_plane;
|
||||
@ -1586,24 +1694,35 @@ int vc4_plane_create_additional_planes(struct drm_device *drm)
|
||||
* modest number of planes to expose, that should hopefully
|
||||
* still cover any sane usecase.
|
||||
*/
|
||||
for (i = 0; i < 16; i++) {
|
||||
for (i = 0; i < VC4_NUM_OVERLAY_PLANES; i++) {
|
||||
struct drm_plane *plane =
|
||||
vc4_plane_init(drm, DRM_PLANE_TYPE_OVERLAY,
|
||||
GENMASK(drm->mode_config.num_crtc - 1, 0));
|
||||
|
||||
if (IS_ERR(plane))
|
||||
continue;
|
||||
|
||||
/* Create zpos property. Max of all the overlays + 1 primary +
|
||||
* 1 cursor plane on a crtc.
|
||||
*/
|
||||
drm_plane_create_zpos_property(plane, i + 1, 1,
|
||||
VC4_NUM_OVERLAY_PLANES + 1);
|
||||
}
|
||||
|
||||
drm_for_each_crtc(crtc, drm) {
|
||||
/* Set up the legacy cursor after overlay initialization,
|
||||
* since we overlay planes on the CRTC in the order they were
|
||||
* initialized.
|
||||
* since the zpos fallback is that planes are rendered by plane
|
||||
* ID order, and that then puts the cursor on top.
|
||||
*/
|
||||
cursor_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_CURSOR,
|
||||
drm_crtc_mask(crtc));
|
||||
if (!IS_ERR(cursor_plane)) {
|
||||
crtc->cursor = cursor_plane;
|
||||
|
||||
drm_plane_create_zpos_property(cursor_plane,
|
||||
VC4_NUM_OVERLAY_PLANES + 1,
|
||||
1,
|
||||
VC4_NUM_OVERLAY_PLANES + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,6 +220,12 @@
|
||||
#define SCALER_DISPCTRL 0x00000000
|
||||
/* Global register for clock gating the HVS */
|
||||
# define SCALER_DISPCTRL_ENABLE BIT(31)
|
||||
# define SCALER_DISPCTRL_PANIC0_MASK VC4_MASK(25, 24)
|
||||
# define SCALER_DISPCTRL_PANIC0_SHIFT 24
|
||||
# define SCALER_DISPCTRL_PANIC1_MASK VC4_MASK(27, 26)
|
||||
# define SCALER_DISPCTRL_PANIC1_SHIFT 26
|
||||
# define SCALER_DISPCTRL_PANIC2_MASK VC4_MASK(29, 28)
|
||||
# define SCALER_DISPCTRL_PANIC2_SHIFT 28
|
||||
# define SCALER_DISPCTRL_DSP3_MUX_MASK VC4_MASK(19, 18)
|
||||
# define SCALER_DISPCTRL_DSP3_MUX_SHIFT 18
|
||||
|
||||
@ -228,15 +234,21 @@
|
||||
* always enabled.
|
||||
*/
|
||||
# define SCALER_DISPCTRL_DSPEISLUR(x) BIT(13 + (x))
|
||||
# define SCALER5_DISPCTRL_DSPEISLUR(x) BIT(9 + ((x) * 4))
|
||||
/* Enables Display 0 end-of-line-N contribution to
|
||||
* SCALER_DISPSTAT_IRQDISP0
|
||||
*/
|
||||
# define SCALER_DISPCTRL_DSPEIEOLN(x) BIT(8 + ((x) * 2))
|
||||
# define SCALER5_DISPCTRL_DSPEIEOLN(x) BIT(8 + ((x) * 4))
|
||||
/* Enables Display 0 EOF contribution to SCALER_DISPSTAT_IRQDISP0 */
|
||||
# define SCALER_DISPCTRL_DSPEIEOF(x) BIT(7 + ((x) * 2))
|
||||
# define SCALER5_DISPCTRL_DSPEIEOF(x) BIT(7 + ((x) * 4))
|
||||
|
||||
# define SCALER_DISPCTRL_SLVRDEIRQ BIT(6)
|
||||
# define SCALER_DISPCTRL_SLVWREIRQ BIT(5)
|
||||
# define SCALER5_DISPCTRL_DSPEIVST(x) BIT(6 + ((x) * 4))
|
||||
|
||||
# define SCALER_DISPCTRL_SLVRDEIRQ BIT(6) /* HVS4 only */
|
||||
# define SCALER_DISPCTRL_SLVWREIRQ BIT(5) /* HVS4 only */
|
||||
# define SCALER5_DISPCTRL_SLVEIRQ BIT(5)
|
||||
# define SCALER_DISPCTRL_DMAEIRQ BIT(4)
|
||||
/* Enables interrupt generation on the enabled EOF/EOLN/EISLUR
|
||||
* bits and short frames..
|
||||
@ -360,6 +372,7 @@
|
||||
|
||||
#define SCALER_DISPBKGND0 0x00000044
|
||||
# define SCALER_DISPBKGND_AUTOHS BIT(31)
|
||||
# define SCALER5_DISPBKGND_BCK2BCK BIT(31)
|
||||
# define SCALER_DISPBKGND_INTERLACE BIT(30)
|
||||
# define SCALER_DISPBKGND_GAMMA BIT(29)
|
||||
# define SCALER_DISPBKGND_TESTMODE_MASK VC4_MASK(28, 25)
|
||||
@ -835,16 +848,19 @@ enum hvs_pixel_format {
|
||||
/* Note: the LSB is the rightmost character shown. Only valid for
|
||||
* HVS_PIXEL_FORMAT_RGB8888, not RGB888.
|
||||
*/
|
||||
/* For modes 332, 4444, 555, 5551, 6666, 8888, 10:10:10:2 */
|
||||
#define HVS_PIXEL_ORDER_RGBA 0
|
||||
#define HVS_PIXEL_ORDER_BGRA 1
|
||||
#define HVS_PIXEL_ORDER_ARGB 2
|
||||
#define HVS_PIXEL_ORDER_ABGR 3
|
||||
|
||||
/* For modes 666 and 888 (4 & 5) */
|
||||
#define HVS_PIXEL_ORDER_XBRG 0
|
||||
#define HVS_PIXEL_ORDER_XRBG 1
|
||||
#define HVS_PIXEL_ORDER_XRGB 2
|
||||
#define HVS_PIXEL_ORDER_XBGR 3
|
||||
|
||||
/* For YCbCr modes (8-12, and 17) */
|
||||
#define HVS_PIXEL_ORDER_XYCBCR 0
|
||||
#define HVS_PIXEL_ORDER_XYCRCB 1
|
||||
#define HVS_PIXEL_ORDER_YXCBCR 2
|
||||
|
@ -613,7 +613,9 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder,
|
||||
VEC_WRITE(VEC_CLMP0_START, 0xac);
|
||||
VEC_WRITE(VEC_CLMP0_END, 0xec);
|
||||
VEC_WRITE(VEC_CONFIG2,
|
||||
VEC_CONFIG2_UV_DIG_DIS | VEC_CONFIG2_RGB_DIG_DIS);
|
||||
VEC_CONFIG2_UV_DIG_DIS |
|
||||
VEC_CONFIG2_RGB_DIG_DIS |
|
||||
((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) ? 0 : VEC_CONFIG2_PROG_SCAN));
|
||||
VEC_WRITE(VEC_CONFIG3, VEC_CONFIG3_HORIZ_LEN_STD);
|
||||
VEC_WRITE(VEC_DAC_CONFIG, vec->variant->dac_config);
|
||||
|
||||
|
@ -160,10 +160,44 @@ static int vkms_plane_atomic_check(struct drm_plane *plane,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vkms_prepare_fb(struct drm_plane *plane,
|
||||
struct drm_plane_state *state)
|
||||
{
|
||||
struct drm_shadow_plane_state *shadow_plane_state;
|
||||
struct drm_framebuffer *fb = state->fb;
|
||||
int ret;
|
||||
|
||||
if (!fb)
|
||||
return 0;
|
||||
|
||||
shadow_plane_state = to_drm_shadow_plane_state(state);
|
||||
|
||||
ret = drm_gem_plane_helper_prepare_fb(plane, state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return drm_gem_fb_vmap(fb, shadow_plane_state->map, shadow_plane_state->data);
|
||||
}
|
||||
|
||||
static void vkms_cleanup_fb(struct drm_plane *plane,
|
||||
struct drm_plane_state *state)
|
||||
{
|
||||
struct drm_shadow_plane_state *shadow_plane_state;
|
||||
struct drm_framebuffer *fb = state->fb;
|
||||
|
||||
if (!fb)
|
||||
return;
|
||||
|
||||
shadow_plane_state = to_drm_shadow_plane_state(state);
|
||||
|
||||
drm_gem_fb_vunmap(fb, shadow_plane_state->map);
|
||||
}
|
||||
|
||||
static const struct drm_plane_helper_funcs vkms_primary_helper_funcs = {
|
||||
.atomic_update = vkms_plane_atomic_update,
|
||||
.atomic_check = vkms_plane_atomic_check,
|
||||
DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
|
||||
.prepare_fb = vkms_prepare_fb,
|
||||
.cleanup_fb = vkms_cleanup_fb,
|
||||
};
|
||||
|
||||
struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
|
||||
|
@ -10,8 +10,6 @@ struct drm_connector;
|
||||
struct drm_device;
|
||||
struct drm_encoder;
|
||||
|
||||
void drm_bridge_connector_enable_hpd(struct drm_connector *connector);
|
||||
void drm_bridge_connector_disable_hpd(struct drm_connector *connector);
|
||||
struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
|
||||
struct drm_encoder *encoder);
|
||||
|
||||
|
@ -86,9 +86,22 @@ struct drm_info_node {
|
||||
* core.
|
||||
*/
|
||||
struct drm_debugfs_info {
|
||||
/** @name: File name */
|
||||
const char *name;
|
||||
|
||||
/**
|
||||
* @show:
|
||||
*
|
||||
* Show callback. &seq_file->private will be set to the &struct
|
||||
* drm_debugfs_entry corresponding to the instance of this info
|
||||
* on a given &struct drm_device.
|
||||
*/
|
||||
int (*show)(struct seq_file*, void*);
|
||||
|
||||
/** @driver_features: Required driver features for this entry. */
|
||||
u32 driver_features;
|
||||
|
||||
/** @data: Driver-private data, should not be device-specific. */
|
||||
void *data;
|
||||
};
|
||||
|
||||
@ -99,8 +112,13 @@ struct drm_debugfs_info {
|
||||
* drm_debugfs_info on a &struct drm_device.
|
||||
*/
|
||||
struct drm_debugfs_entry {
|
||||
/** @dev: &struct drm_device for this node. */
|
||||
struct drm_device *dev;
|
||||
|
||||
/** @file: Template for this node. */
|
||||
struct drm_debugfs_info file;
|
||||
|
||||
/** @list: Linked list of all device nodes. */
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
|
@ -87,10 +87,23 @@ struct drm_device {
|
||||
*/
|
||||
void *dev_private;
|
||||
|
||||
/** @primary: Primary node */
|
||||
/**
|
||||
* @primary:
|
||||
*
|
||||
* Primary node. Drivers should not interact with this
|
||||
* directly. debugfs interfaces can be registered with
|
||||
* drm_debugfs_add_file(), and sysfs should be directly added on the
|
||||
* hardware (and not character device node) struct device @dev.
|
||||
*/
|
||||
struct drm_minor *primary;
|
||||
|
||||
/** @render: Render node */
|
||||
/**
|
||||
* @render:
|
||||
*
|
||||
* Render node. Drivers should not interact with this directly ever.
|
||||
* Drivers should not expose any additional interfaces in debugfs or
|
||||
* sysfs on this node.
|
||||
*/
|
||||
struct drm_minor *render;
|
||||
|
||||
/** @accel: Compute Acceleration node */
|
||||
|
@ -30,12 +30,27 @@ void drm_fb_xrgb8888_to_rgb332(struct iosys_map *dst, const unsigned int *dst_pi
|
||||
void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip, bool swab);
|
||||
void drm_fb_xrgb8888_to_xrgb1555(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip);
|
||||
void drm_fb_xrgb8888_to_argb1555(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip);
|
||||
void drm_fb_xrgb8888_to_rgba5551(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip);
|
||||
void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip);
|
||||
void drm_fb_xrgb8888_to_argb8888(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip);
|
||||
void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip);
|
||||
void drm_fb_xrgb8888_to_argb2101010(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip);
|
||||
void drm_fb_xrgb8888_to_gray8(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip);
|
||||
@ -50,7 +65,6 @@ void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitc
|
||||
|
||||
size_t drm_fb_build_fourcc_list(struct drm_device *dev,
|
||||
const u32 *native_fourccs, size_t native_nfourccs,
|
||||
const u32 *extra_fourccs, size_t extra_nfourccs,
|
||||
u32 *fourccs_out, size_t nfourccs_out);
|
||||
|
||||
#endif /* __LINUX_DRM_FORMAT_HELPER_H */
|
||||
|
@ -297,21 +297,42 @@ int mipi_dsi_dcs_set_display_brightness(struct mipi_dsi_device *dsi,
|
||||
int mipi_dsi_dcs_get_display_brightness(struct mipi_dsi_device *dsi,
|
||||
u16 *brightness);
|
||||
|
||||
/**
|
||||
* mipi_dsi_generic_write_seq - transmit data using a generic write packet
|
||||
* @dsi: DSI peripheral device
|
||||
* @seq: buffer containing the payload
|
||||
*/
|
||||
#define mipi_dsi_generic_write_seq(dsi, seq...) \
|
||||
do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
struct device *dev = &dsi->dev; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) { \
|
||||
dev_err_ratelimited(dev, "transmit data failed: %d\n", \
|
||||
ret); \
|
||||
return ret; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* mipi_dsi_dcs_write_seq - transmit a DCS command with payload
|
||||
* @dsi: DSI peripheral device
|
||||
* @cmd: Command
|
||||
* @seq: buffer containing data to be transmitted
|
||||
*/
|
||||
#define mipi_dsi_dcs_write_seq(dsi, cmd, seq...) do { \
|
||||
static const u8 d[] = { cmd, seq }; \
|
||||
struct device *dev = &dsi->dev; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) { \
|
||||
dev_err_ratelimited(dev, "sending command %#02x failed: %d\n", cmd, ret); \
|
||||
return ret; \
|
||||
} \
|
||||
#define mipi_dsi_dcs_write_seq(dsi, cmd, seq...) \
|
||||
do { \
|
||||
static const u8 d[] = { cmd, seq }; \
|
||||
struct device *dev = &dsi->dev; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) { \
|
||||
dev_err_ratelimited( \
|
||||
dev, "sending command %#02x failed: %d\n", \
|
||||
cmd, ret); \
|
||||
return ret; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
|
@ -1143,6 +1143,28 @@ struct drm_connector_helper_funcs {
|
||||
*/
|
||||
void (*cleanup_writeback_job)(struct drm_writeback_connector *connector,
|
||||
struct drm_writeback_job *job);
|
||||
|
||||
/**
|
||||
* @enable_hpd:
|
||||
*
|
||||
* Enable hot-plug detection for the connector.
|
||||
*
|
||||
* This operation is optional.
|
||||
*
|
||||
* This callback is used by the drm_kms_helper_poll_enable() helpers.
|
||||
*/
|
||||
void (*enable_hpd)(struct drm_connector *connector);
|
||||
|
||||
/**
|
||||
* @disable_hpd:
|
||||
*
|
||||
* Disable hot-plug detection for the connector.
|
||||
*
|
||||
* This operation is optional.
|
||||
*
|
||||
* This callback is used by the drm_kms_helper_poll_disable() helpers.
|
||||
*/
|
||||
void (*disable_hpd)(struct drm_connector *connector);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -88,6 +88,18 @@ extern "C" {
|
||||
*
|
||||
* The authoritative list of format modifier codes is found in
|
||||
* `include/uapi/drm/drm_fourcc.h`
|
||||
*
|
||||
* Open Source User Waiver
|
||||
* -----------------------
|
||||
*
|
||||
* Because this is the authoritative source for pixel formats and modifiers
|
||||
* referenced by GL, Vulkan extensions and other standards and hence used both
|
||||
* by open source and closed source driver stacks, the usual requirement for an
|
||||
* upstream in-kernel or open source userspace user does not apply.
|
||||
*
|
||||
* To ensure, as much as feasible, compatibility across stacks and avoid
|
||||
* confusion with incompatible enumerations stakeholders for all relevant driver
|
||||
* stacks should approve additions.
|
||||
*/
|
||||
|
||||
#define fourcc_code(a, b, c, d) ((__u32)(a) | ((__u32)(b) << 8) | \
|
||||
|
Loading…
Reference in New Issue
Block a user