diff options
author | Dave Airlie <airlied@redhat.com> | 2023-01-16 15:33:22 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2023-01-16 15:33:28 +1000 |
commit | c37ea39c1fa880da0d7fd2c719e5c96be19f0fc5 (patch) | |
tree | 1d4bd8a5ab631cd54ebb326fc39160a2be84e969 | |
parent | 1f1c24dee225fc82472627986997ba6aef309fc2 (diff) | |
parent | 6e41acd2e5353c5362e0d5c2f5ba495c54ff555e (diff) |
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
81 files changed, 3119 insertions, 1350 deletions
diff --git a/Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml b/Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml new file mode 100644 index 000000000000..1b2a1baa26f9 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml @@ -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>; + }; + }; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/display/panel/visionox,vtdr6130.yaml b/Documentation/devicetree/bindings/display/panel/visionox,vtdr6130.yaml new file mode 100644 index 000000000000..49e2fd4b4e99 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/visionox,vtdr6130.yaml @@ -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>; + }; + }; + }; +... diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst index eb045fc495a4..e48101c970cc 100644 --- a/Documentation/userspace-api/ioctl/ioctl-number.rst +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst @@ -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! diff --git a/MAINTAINERS b/MAINTAINERS index a47d963af3b8..7fc9e31ab03f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -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 diff --git a/drivers/firmware/sysfb_simplefb.c b/drivers/firmware/sysfb_simplefb.c index a353e27f83f5..ce9c007ed66f 100644 --- a/drivers/firmware/sysfb_simplefb.c +++ b/drivers/firmware/sysfb_simplefb.c @@ -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; diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 9f019cd053e1..748b93d00184 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -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 diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig b/drivers/gpu/drm/amd/amdgpu/Kconfig index 5fcd510f1abb..5341b6b242c3 100644 --- a/drivers/gpu/drm/amd/amdgpu/Kconfig +++ b/drivers/gpu/drm/amd/amdgpu/Kconfig @@ -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 diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c index 7043d1c9ed8f..e3507dd6f82a 100644 --- a/drivers/gpu/drm/arm/hdlcd_drv.c +++ b/drivers/gpu/drm/arm/hdlcd_drv.c @@ -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; diff --git a/drivers/gpu/drm/ast/Kconfig b/drivers/gpu/drm/ast/Kconfig index d367a90cd3de..563fa7a3b546 100644 --- a/drivers/gpu/drm/ast/Kconfig +++ b/drivers/gpu/drm/ast/Kconfig @@ -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, diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c index 1708098fba6d..e8aae3cdc73d 100644 --- a/drivers/gpu/drm/bridge/panel.c +++ b/drivers/gpu/drm/bridge/panel.c @@ -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); diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c index b4c8cab7158c..6e74de833466 100644 --- a/drivers/gpu/drm/drm_blend.c +++ b/drivers/gpu/drm/drm_blend.c @@ -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; diff --git a/drivers/gpu/drm/drm_bridge_connector.c b/drivers/gpu/drm/drm_bridge_connector.c index 1c7d936523df..19ae4a177ac3 100644 --- a/drivers/gpu/drm/drm_bridge_connector.c +++ b/drivers/gpu/drm/drm_bridge_connector.c @@ -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; diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 5ea237839439..4f643a490dc3 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -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 */ diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index b3a731b9170a..427631706128 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -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_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; - - 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; + uint32_t format; + size_t i; /* - * If driver picks 8 or 16 by default use that for both depth/bpp - * to begin with + * 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 (preferred_bpp != sizes.surface_bpp) - sizes.surface_depth = sizes.surface_bpp = preferred_bpp; + format = drm_mode_legacy_fb_format(bpp, depth); + if (!format) + goto err; - 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; + for (i = 0; i < format_count; ++i) { + if (formats[i] == format) + return format; + } - cmdline_mode = &connector->cmdline_mode; +err: + /* We found nothing. */ + drm_warn(dev, "bpp/depth value of %u/%u not supported\n", bpp, depth); - 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; - } + 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; } - 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); + 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; + int crtc_count = 0; + struct drm_connector_list_iter conn_iter; + struct drm_connector *connector; + struct drm_mode_set *mode_set; + uint32_t surface_format = DRM_FORMAT_INVALID; + const struct drm_format_info *info; + + memset(sizes, 0, sizeof(*sizes)); + sizes->fb_width = (u32)-1; + sizes->fb_height = (u32)-1; + 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; - - 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) - continue; - - /* We found a perfect fit, great */ - if (fmt->depth == sizes.surface_depth) { - best_depth = fmt->depth; - break; - } + 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; - /* Skip depths above what we're looking for */ - if (fmt->depth > sizes.surface_depth) + if (!cmdline_mode->bpp_specified) 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) diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index 64b4a3a87fbb..a51ff8cee049 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -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); diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 74ff33c2ddaa..994f8fb71f45 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -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; - unsigned int x; - - 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; + const __le32 *sbuf32 = sbuf; unsigned int x; + u32 pix; 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) { - drm_fb_xrgb8888_to_rgb888(dst, dst_pitch, src, fb, clip); + } 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_XRGB8888) { - if (fb_format == DRM_FORMAT_RGB888) { - drm_fb_rgb888_to_xrgb8888(dst, dst_pitch, src, fb, clip); + } 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 (fb_format == DRM_FORMAT_RGB565) { - drm_fb_rgb565_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 (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); diff --git a/drivers/gpu/drm/drm_gem_dma_helper.c b/drivers/gpu/drm/drm_gem_dma_helper.c index 1e658c448366..df89fbd2d35c 100644 --- a/drivers/gpu/drm/drm_gem_dma_helper.c +++ b/drivers/gpu/drm/drm_gem_dma_helper.c @@ -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; } diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c index f21f47737817..235832ad7a79 100644 --- a/drivers/gpu/drm/drm_gem_shmem_helper.c +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c @@ -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; } diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c index 5d82891c3222..49a743f62b4a 100644 --- a/drivers/gpu/drm/drm_ioc32.c +++ b/drivers/gpu/drm/drm_ioc32.c @@ -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); diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index ca2a6e6101dc..7c9d66ee917d 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -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); diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c index d72c2fac0ff1..08ab75303a00 100644 --- a/drivers/gpu/drm/drm_lease.c +++ b/drivers/gpu/drm/drm_lease.c @@ -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)) diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index 33357629a7f5..24e7998d1731 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c @@ -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(). diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 1ea053cef557..7973f2589ced 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -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); diff --git a/drivers/gpu/drm/gma500/Kconfig b/drivers/gpu/drm/gma500/Kconfig index 807b989e3c77..2efc0eb41c64 100644 --- a/drivers/gpu/drm/gma500/Kconfig +++ b/drivers/gpu/drm/gma500/Kconfig @@ -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 diff --git a/drivers/gpu/drm/gud/gud_drv.c b/drivers/gpu/drm/gud/gud_drv.c index 5aac7cda0505..9d7bf8ee45f1 100644 --- a/drivers/gpu/drm/gud/gud_drv.c +++ b/drivers/gpu/drm/gud/gud_drv.c @@ -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); diff --git a/drivers/gpu/drm/hisilicon/hibmc/Kconfig b/drivers/gpu/drm/hisilicon/hibmc/Kconfig index 4e41c144a290..126504318a4f 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/Kconfig +++ b/drivers/gpu/drm/hisilicon/hibmc/Kconfig @@ -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. diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c index b9788218b2ec..923389f22020 100644 --- a/drivers/gpu/drm/i2c/ch7006_drv.c +++ b/drivers/gpu/drm/i2c/ch7006_drv.c @@ -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 = { diff --git a/drivers/gpu/drm/i2c/sil164_drv.c b/drivers/gpu/drm/i2c/sil164_drv.c index 1bc0b5de4499..f57f9a807542 100644 --- a/drivers/gpu/drm/i2c/sil164_drv.c +++ b/drivers/gpu/drm/i2c/sil164_drv.c @@ -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", }, diff --git a/drivers/gpu/drm/i2c/tda9950.c b/drivers/gpu/drm/i2c/tda9950.c index 9ed54e7ccff2..b8c143e573e0 100644 --- a/drivers/gpu/drm/i2c/tda9950.c +++ b/drivers/gpu/drm/i2c/tda9950.c @@ -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", diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index a14d2896aebb..db5c9343a3d2 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -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", diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 3efce05d7b57..c6e3792622f2 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -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 diff --git a/drivers/gpu/drm/imx/dcss/dcss-dev.c b/drivers/gpu/drm/imx/dcss/dcss-dev.c index 66d9233ffb98..5d1779ab65c0 100644 --- a/drivers/gpu/drm/imx/dcss/dcss-dev.c +++ b/drivers/gpu/drm/imx/dcss/dcss-dev.c @@ -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; } diff --git a/drivers/gpu/drm/imx/dcss/dcss-drv.c b/drivers/gpu/drm/imx/dcss/dcss-drv.c index 431510bd811b..4f2291610139 100644 --- a/drivers/gpu/drm/imx/dcss/dcss-drv.c +++ b/drivers/gpu/drm/imx/dcss/dcss-drv.c @@ -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; diff --git a/drivers/gpu/drm/imx/dcss/dcss-kms.c b/drivers/gpu/drm/imx/dcss/dcss-kms.c index 18df3888b7f9..dab5e664920d 100644 --- a/drivers/gpu/drm/imx/dcss/dcss-kms.c +++ b/drivers/gpu/drm/imx/dcss/dcss-kms.c @@ -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); diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c index 7642f740272b..534621a13a34 100644 --- a/drivers/gpu/drm/meson/meson_dw_hdmi.c +++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c @@ -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, diff --git a/drivers/gpu/drm/mgag200/Kconfig b/drivers/gpu/drm/mgag200/Kconfig index eec59658a938..b28c5e4828f4 100644 --- a/drivers/gpu/drm/mgag200/Kconfig +++ b/drivers/gpu/drm/mgag200/Kconfig @@ -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 diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 4d3fdc806bef..c373a40bef37 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -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); diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c index 810edea0a31e..b3ab86ad1b36 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c @@ -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)) diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig index 03d12caf9e26..a0bb3987bf63 100644 --- a/drivers/gpu/drm/nouveau/Kconfig +++ b/drivers/gpu/drm/nouveau/Kconfig @@ -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 diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index eaf67b9e5f12..699ed814e021 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -546,44 +546,6 @@ static void omap_modeset_fini(struct drm_device *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); diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 114758f64d26..dd79928f5482 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -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 diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index ddcf8df889c8..d07e6fa28bdf 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -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 diff --git a/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c b/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c index b3235781e6ba..075a7af81eff 100644 --- a/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c +++ b/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c @@ -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; } diff --git a/drivers/gpu/drm/panel/panel-boe-bf060y8m-aj0.c b/drivers/gpu/drm/panel/panel-boe-bf060y8m-aj0.c index ad58840eda41..90098b753e3b 100644 --- a/drivers/gpu/drm/panel/panel-boe-bf060y8m-aj0.c +++ b/drivers/gpu/drm/panel/panel-boe-bf060y8m-aj0.c @@ -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); diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index a0a7ab35e08c..01bfe0783304 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -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"), diff --git a/drivers/gpu/drm/panel/panel-elida-kd35t133.c b/drivers/gpu/drm/panel/panel-elida-kd35t133.c index eee714cf3f49..e7be15b68102 100644 --- a/drivers/gpu/drm/panel/panel-elida-kd35t133.c +++ b/drivers/gpu/drm/panel/panel-elida-kd35t133.c @@ -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"); diff --git a/drivers/gpu/drm/panel/panel-himax-hx8394.c b/drivers/gpu/drm/panel/panel-himax-hx8394.c new file mode 100644 index 000000000000..d4fb5d1b295b --- /dev/null +++ b/drivers/gpu/drm/panel/panel-himax-hx8394.c @@ -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"); diff --git a/drivers/gpu/drm/panel/panel-jdi-fhd-r63452.c b/drivers/gpu/drm/panel/panel-jdi-fhd-r63452.c index d8765b2294fb..8912757a6f42 100644 --- a/drivers/gpu/drm/panel/panel-jdi-fhd-r63452.c +++ b/drivers/gpu/drm/panel/panel-jdi-fhd-r63452.c @@ -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) { diff --git a/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c b/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c index 5619f186d28c..d2efd887484b 100644 --- a/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c +++ b/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c @@ -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); - - 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, 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); + + 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) { diff --git a/drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c b/drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c index 772e3b6acece..9243b2ad828d 100644 --- a/drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c +++ b/drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c @@ -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"); diff --git a/drivers/gpu/drm/panel/panel-novatek-nt35950.c b/drivers/gpu/drm/panel/panel-novatek-nt35950.c index 3a844917da07..abf752b36a52 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt35950.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt35950.c @@ -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); diff --git a/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c b/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c index 36a46cb7fe1c..aba556c98300 100644 --- a/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c +++ b/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c @@ -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, }; diff --git a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c index 79f852465a84..1ef1cfd01c77 100644 --- a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c +++ b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c @@ -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, }; diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c b/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c index 97ff7a18545c..7431cae7427e 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c @@ -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) { diff --git a/drivers/gpu/drm/panel/panel-samsung-sofef00.c b/drivers/gpu/drm/panel/panel-samsung-sofef00.c index 1a0d24595faa..9db49a028930 100644 --- a/drivers/gpu/drm/panel/panel-samsung-sofef00.c +++ b/drivers/gpu/drm/panel/panel-samsung-sofef00.c @@ -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) { diff --git a/drivers/gpu/drm/panel/panel-sharp-ls060t1sx01.c b/drivers/gpu/drm/panel/panel-sharp-ls060t1sx01.c index 8a4e0c1fe73f..68f52eaaf4fa 100644 --- a/drivers/gpu/drm/panel/panel-sharp-ls060t1sx01.c +++ b/drivers/gpu/drm/panel/panel-sharp-ls060t1sx01.c @@ -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) { diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c b/drivers/gpu/drm/panel/panel-sitronix-st7703.c index 86a472b01360..6747ca237ced 100644 --- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c +++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c @@ -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); - - 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_SETEXTC, 0xF1, 0x12, 0x83); + + 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); + + 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 - */); - - 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_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_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); - - 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_UNKNOWN_C6, 0x01, 0x00, 0xFF, 0xFF, 0x00); + + 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); diff --git a/drivers/gpu/drm/panel/panel-sony-tulip-truly-nt35521.c b/drivers/gpu/drm/panel/panel-sony-tulip-truly-nt35521.c index fa9be3c299c0..ee5d20ecc577 100644 --- a/drivers/gpu/drm/panel/panel-sony-tulip-truly-nt35521.c +++ b/drivers/gpu/drm/panel/panel-sony-tulip-truly-nt35521.c @@ -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; } diff --git a/drivers/gpu/drm/panel/panel-visionox-vtdr6130.c b/drivers/gpu/drm/panel/panel-visionox-vtdr6130.c new file mode 100644 index 000000000000..f9a6abc1e121 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-visionox-vtdr6130.c @@ -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"); diff --git a/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c b/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c index 2c54733ee241..8670386498a4 100644 --- a/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c +++ b/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c @@ -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); diff --git a/drivers/gpu/drm/radeon/Kconfig b/drivers/gpu/drm/radeon/Kconfig index 97a277f9a25e..62a596d3a891 100644 --- a/drivers/gpu/drm/radeon/Kconfig +++ b/drivers/gpu/drm/radeon/Kconfig @@ -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 diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c index 567c71f95edc..34e80eb6d96e 100644 --- a/drivers/gpu/drm/tests/drm_format_helper_test.c +++ b/drivers/gpu/drm/tests/drm_format_helper_test.c @@ -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), {} }; diff --git a/drivers/gpu/drm/tiny/ofdrm.c b/drivers/gpu/drm/tiny/ofdrm.c index 33eefeba437c..6e349ca42485 100644 --- a/drivers/gpu/drm/tiny/ofdrm.c +++ b/drivers/gpu/drm/tiny/ofdrm.c @@ -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; } diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c index 30e928d627e8..f658b99c796a 100644 --- a/drivers/gpu/drm/tiny/simpledrm.c +++ b/drivers/gpu/drm/tiny/simpledrm.c @@ -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; } diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c index 6e152ef26358..5da1806f3969 100644 --- a/drivers/gpu/drm/v3d/v3d_gem.c +++ b/drivers/gpu/drm/v3d/v3d_gem.c @@ -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) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 35a6b5907278..cdc0559221f0 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -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); diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c index e05be9a34156..2a71321b9222 100644 --- a/drivers/gpu/drm/vc4/vc4_dsi.c +++ b/drivers/gpu/drm/vc4/vc4_dsi.c @@ -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> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index dfb7f41b28df..14628864487a 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -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; diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c index 024a2cdff5b2..4da66ef96783 100644 --- a/drivers/gpu/drm/vc4/vc4_hvs.c +++ b/drivers/gpu/drm/vc4/vc4_hvs.c @@ -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) diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 53d9f30460cf..a7e3d47c50f4 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -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) diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 8b92a45a3c89..dee525bacd4b 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -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); } } diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h index f0290fad991d..f3763bd600f6 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h @@ -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 diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c index d8bf00b442e9..a3782d05cd66 100644 --- a/drivers/gpu/drm/vc4/vc4_vec.c +++ b/drivers/gpu/drm/vc4/vc4_vec.c @@ -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); diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index c3a845220e10..b3f8a115cc23 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -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, diff --git a/include/drm/drm_bridge_connector.h b/include/drm/drm_bridge_connector.h index 33f6c3bbdb4a..69630815fb09 100644 --- a/include/drm/drm_bridge_connector.h +++ b/include/drm/drm_bridge_connector.h @@ -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); diff --git a/include/drm/drm_debugfs.h b/include/drm/drm_debugfs.h index 53b7297260a5..7616f457ce70 100644 --- a/include/drm/drm_debugfs.h +++ b/include/drm/drm_debugfs.h @@ -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; }; diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h index a68c6a312b46..7cf4afae2e79 100644 --- a/include/drm/drm_device.h +++ b/include/drm/drm_device.h @@ -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 */ diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index eb5c98cf82b8..291deb09475b 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -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 */ diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h index 20b21b577dea..4f503d99f668 100644 --- a/include/drm/drm_mipi_dsi.h +++ b/include/drm/drm_mipi_dsi.h @@ -298,20 +298,41 @@ 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) /** diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index d9f2254a039a..77a540ad7dcd 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h @@ -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); }; /** diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index bc056f2d537d..de703c6be969 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -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) | \ |