Merge tag 'drm-misc-next-2024-02-08' of git://anongit.freedesktop.org/drm/drm-misc into drm-next

drm-misc-next for v6.9:

UAPI Changes:

Cross-subsystem Changes:

dma-buf:
- clean up docs

media:
- tc358743: fix v4l device registration

video:
- move all kernel parameters for video behind CONFIG_VIDEO

sound:
- remove <drm/drm_edid.h> include from header

Core Changes:

ci:
- add tests for msm

managed:
- add drmm_release_action() with tests

ttm:
- fix errno codes
- simply busy-placement handling
- fix page decryption

docs:
- add new external references
- clean up

Driver Changes:

amdgpu:
- clean up

bridge:
- imx: add i.MX8MP HDMI PVI plus DT bindings, add i.MX8MP HDMI TX plus DT
  bindings
- samsung-dsim: add bsh-smm-s2/pro boards
- sii902x: fix probing and unregistration
- tc358767: limit pixel PLL input range
- switch to new drm_bridge_read_edid() interface
- clean up

imx:
- use devm_ functions during init
- clean up

lima:
- fix memory leak

loongson:
- fail if no VRAM present

meson:
- switch to new drm_bridge_read_edid() interface

nouveau:
- clean up

panel:
- add BOE TH101MB31IG002-28A plus DT bindings
- add EDT ETML1010G3DRA plus DT bindings
- add Novatek NT36672E LCD DSI plus DT bindings
- nt36523: support 120Hz timings, fix includes
- simple: fix display timings on RK32FN48H
- visionox-vtdr6130: fix initialization

panel-orientation-quirks:
- GPD Win Mini

vmwgfx:
- list command SVGA_3D_CMD_DEFINE_GB_SURFACE_V4 as invalid
- fix null-pointer deref in execbuf
- refactor display-mode probing
- fix fencing for creating cursor MOBs
- fix cursor-memory lifetime
- clean up

xlnx:
- fix live video input for ZynqMP DPSUB

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20240208164242.GA14321@linux.fritz.box
This commit is contained in:
Dave Airlie
2024-02-12 13:00:53 +10:00
133 changed files with 2636 additions and 983 deletions
@@ -0,0 +1,102 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/bridge/fsl,imx8mp-hdmi-tx.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Freescale i.MX8MP DWC HDMI TX Encoder
maintainers:
- Lucas Stach <l.stach@pengutronix.de>
description:
The i.MX8MP HDMI transmitter is a Synopsys DesignWare
HDMI 2.0a TX controller IP.
allOf:
- $ref: /schemas/display/bridge/synopsys,dw-hdmi.yaml#
properties:
compatible:
enum:
- fsl,imx8mp-hdmi-tx
reg-io-width:
const: 1
clocks:
maxItems: 4
clock-names:
items:
- const: iahb
- const: isfr
- const: cec
- const: pix
power-domains:
maxItems: 1
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: /schemas/graph.yaml#/properties/port
description: Parallel RGB input port
port@1:
$ref: /schemas/graph.yaml#/properties/port
description: HDMI output port
required:
- port@0
- port@1
required:
- compatible
- reg
- clocks
- clock-names
- interrupts
- power-domains
- ports
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/imx8mp-clock.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/power/imx8mp-power.h>
hdmi@32fd8000 {
compatible = "fsl,imx8mp-hdmi-tx";
reg = <0x32fd8000 0x7eff>;
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX8MP_CLK_HDMI_APB>,
<&clk IMX8MP_CLK_HDMI_REF_266M>,
<&clk IMX8MP_CLK_32K>,
<&hdmi_tx_phy>;
clock-names = "iahb", "isfr", "cec", "pix";
power-domains = <&hdmi_blk_ctrl IMX8MP_HDMIBLK_PD_HDMI_TX>;
reg-io-width = <1>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
hdmi_tx_from_pvi: endpoint {
remote-endpoint = <&pvi_to_hdmi_tx>;
};
};
port@1 {
reg = <1>;
hdmi_tx_out: endpoint {
remote-endpoint = <&hdmi0_con>;
};
};
};
};
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: SN65DSI86 DSI to eDP bridge chip
maintainers:
- Sandeep Panda <spanda@codeaurora.org>
- Douglas Anderson <dianders@chromium.org>
description: |
The Texas Instruments SN65DSI86 bridge takes MIPI DSI in and outputs eDP.
@@ -0,0 +1,84 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/imx/fsl,imx8mp-hdmi-pvi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Freescale i.MX8MP HDMI Parallel Video Interface
maintainers:
- Lucas Stach <l.stach@pengutronix.de>
description:
The HDMI parallel video interface is a timing and sync generator block in the
i.MX8MP SoC, that sits between the video source and the HDMI TX controller.
properties:
compatible:
const: fsl,imx8mp-hdmi-pvi
reg:
maxItems: 1
interrupts:
maxItems: 1
power-domains:
maxItems: 1
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: /schemas/graph.yaml#/properties/port
description: Input from the LCDIF controller.
port@1:
$ref: /schemas/graph.yaml#/properties/port
description: Output to the HDMI TX controller.
required:
- port@0
- port@1
required:
- compatible
- reg
- interrupts
- power-domains
- ports
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/power/imx8mp-power.h>
display-bridge@32fc4000 {
compatible = "fsl,imx8mp-hdmi-pvi";
reg = <0x32fc4000 0x44>;
interrupt-parent = <&irqsteer_hdmi>;
interrupts = <12 IRQ_TYPE_LEVEL_HIGH>;
power-domains = <&hdmi_blk_ctrl IMX8MP_HDMIBLK_PD_PVI>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
pvi_from_lcdif3: endpoint {
remote-endpoint = <&lcdif3_to_pvi>;
};
};
port@1 {
reg = <1>;
pvi_to_hdmi_tx: endpoint {
remote-endpoint = <&hdmi_tx_from_pvi>;
};
};
};
};
@@ -0,0 +1,58 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/panel/boe,th101mb31ig002-28a.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: BOE TH101MB31IG002-28A WXGA DSI Display Panel
maintainers:
- Manuel Traut <manut@mecka.net>
allOf:
- $ref: panel-common.yaml#
properties:
compatible:
enum:
# BOE TH101MB31IG002-28A 10.1" WXGA TFT LCD panel
- boe,th101mb31ig002-28a
reg: true
backlight: true
enable-gpios: true
power-supply: true
port: true
rotation: true
required:
- compatible
- reg
- enable-gpios
- power-supply
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
dsi {
#address-cells = <1>;
#size-cells = <0>;
panel@0 {
compatible = "boe,th101mb31ig002-28a";
reg = <0>;
backlight = <&backlight_lcd0>;
enable-gpios = <&gpio 45 GPIO_ACTIVE_HIGH>;
rotation = <90>;
power-supply = <&vcc_3v3>;
port {
panel_in_dsi: endpoint {
remote-endpoint = <&dsi_out_con>;
};
};
};
};
...
@@ -0,0 +1,66 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/panel/novatek,nt36672e.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Novatek NT36672E LCD DSI Panel
maintainers:
- Ritesh Kumar <quic_riteshk@quicinc.com>
allOf:
- $ref: panel-common.yaml#
properties:
compatible:
const: novatek,nt36672e
reg:
maxItems: 1
description: DSI virtual channel
vddi-supply: true
avdd-supply: true
avee-supply: true
port: true
reset-gpios: true
backlight: true
required:
- compatible
- reg
- vddi-supply
- avdd-supply
- avee-supply
- reset-gpios
- port
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
dsi {
#address-cells = <1>;
#size-cells = <0>;
panel@0 {
compatible = "novatek,nt36672e";
reg = <0>;
reset-gpios = <&tlmm 44 GPIO_ACTIVE_HIGH>;
vddi-supply = <&vreg_l8c_1p8>;
avdd-supply = <&disp_avdd>;
avee-supply = <&disp_avee>;
backlight = <&pwm_backlight>;
port {
panel0_in: endpoint {
remote-endpoint = <&dsi0_out>;
};
};
};
};
...
@@ -141,6 +141,8 @@ properties:
- edt,etm0700g0edh6
# Emerging Display Technology Corp. LVDS WSVGA TFT Display with capacitive touch
- edt,etml0700y5dha
# Emerging Display Technology Corp. 10.1" LVDS WXGA TFT Display with capacitive touch
- edt,etml1010g3dra
# Emerging Display Technology Corp. 5.7" VGA TFT LCD panel with
# capacitive touch
- edt,etmv570g2dhu
@@ -7,7 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Visionox model RM69299 Panels
maintainers:
- Harigovindan P <harigovi@codeaurora.org>
- Abhinav Kumar <quic_abhinavk@quicinc.com>
- Jessica Zhang <quic_jesszhan@quicinc.com>
description: |
This binding is for display panels using a Visionox RM692999 panel.
-12
View File
@@ -153,18 +153,6 @@ Managed Resources
.. kernel-doc:: include/drm/drm_managed.h
:internal:
Bus-specific Device Registration and PCI Support
------------------------------------------------
A number of functions are provided to help with device registration. The
functions deal with PCI and platform devices respectively and are only
provided for historical reasons. These are all deprecated and shouldn't
be used in new drivers. Besides that there's a few helpers for pci
drivers.
.. kernel-doc:: drivers/gpu/drm/drm_pci.c
:export:
Open/Close, File Operations and IOCTLs
======================================
+2
View File
@@ -164,6 +164,8 @@ Conference talks
Slides and articles
-------------------
* `The Linux graphics stack in a nutshell, part 1 <https://lwn.net/Articles/955376/>`_ - Thomas Zimmermann (2023)
* `The Linux graphics stack in a nutshell, part 2 <https://lwn.net/Articles/955708/>`_ - Thomas Zimmermann (2023)
* `Understanding the Linux Graphics Stack <https://bootlin.com/doc/training/graphics/graphics-slides.pdf>`_ - Bootlin (2022)
* `DRM KMS overview <https://wiki.st.com/stm32mpu/wiki/DRM_KMS_overview>`_ - STMicroelectronics (2021)
* `Linux graphic stack <https://studiopixl.com/2017-05-13/linux-graphic-stack-an-overview>`_ - Nathan Gauër (2017)
-4
View File
@@ -31,7 +31,3 @@ host such documentation:
.. toctree::
i915_vm_bind.rst
.. toctree::
xe.rst
+1
View File
@@ -7308,6 +7308,7 @@ F: drivers/gpu/drm/xlnx/
DRM GPU SCHEDULER
M: Luben Tuikov <ltuikov89@gmail.com>
M: Matthew Brost <matthew.brost@intel.com>
L: dri-devel@lists.freedesktop.org
S: Maintained
T: git git://anongit.freedesktop.org/drm/drm-misc
+4 -4
View File
@@ -102,7 +102,7 @@ static atomic64_t dma_fence_context_counter = ATOMIC64_INIT(1);
*
* * Drivers are allowed to call dma_fence_wait() from their &mmu_notifier
* respectively &mmu_interval_notifier callbacks. This means any code required
* for fence completeion cannot allocate memory with GFP_NOFS or GFP_NOIO.
* for fence completion cannot allocate memory with GFP_NOFS or GFP_NOIO.
* Only GFP_ATOMIC is permissible, which might fail.
*
* Note that only GPU drivers have a reasonable excuse for both requiring
@@ -522,7 +522,7 @@ dma_fence_wait_timeout(struct dma_fence *fence, bool intr, signed long timeout)
EXPORT_SYMBOL(dma_fence_wait_timeout);
/**
* dma_fence_release - default relese function for fences
* dma_fence_release - default release function for fences
* @kref: &dma_fence.recfount
*
* This is the default release functions for &dma_fence. Drivers shouldn't call
@@ -974,8 +974,8 @@ void dma_fence_set_deadline(struct dma_fence *fence, ktime_t deadline)
EXPORT_SYMBOL(dma_fence_set_deadline);
/**
* dma_fence_describe - Dump fence describtion into seq_file
* @fence: the 6fence to describe
* dma_fence_describe - Dump fence description into seq_file
* @fence: the fence to describe
* @seq: the seq_file to put the textual description into
*
* Dump a textual description of the fence and it's state into the seq_file.
+2 -2
View File
@@ -405,7 +405,7 @@ static void dma_resv_iter_walk_unlocked(struct dma_resv_iter *cursor)
*
* Beware that the iterator can be restarted. Code which accumulates statistics
* or similar needs to check for this with dma_resv_iter_is_restarted(). For
* this reason prefer the locked dma_resv_iter_first() whenver possible.
* this reason prefer the locked dma_resv_iter_first() whenever possible.
*
* Returns the first fence from an unlocked dma_resv obj.
*/
@@ -428,7 +428,7 @@ EXPORT_SYMBOL(dma_resv_iter_first_unlocked);
*
* Beware that the iterator can be restarted. Code which accumulates statistics
* or similar needs to check for this with dma_resv_iter_is_restarted(). For
* this reason prefer the locked dma_resv_iter_next() whenver possible.
* this reason prefer the locked dma_resv_iter_next() whenever possible.
*
* Returns the next fence from an unlocked dma_resv obj.
*/
+1 -2
View File
@@ -19,8 +19,7 @@ menuconfig DRM
# gallium uses SYS_kcmp for os_same_file_description() to de-duplicate
# device and dmabuf fd. Let's make sure that is available for our userspace.
select KCMP
select VIDEO_CMDLINE
select VIDEO_NOMODESET
select VIDEO
help
Kernel-level support for the Direct Rendering Infrastructure (DRI)
introduced in XFree86 4.0. If you say Y here, you need to select
+2 -1
View File
@@ -329,7 +329,8 @@ int amdgpu_gfx_kiq_init_ring(struct amdgpu_device *adev,
ring->eop_gpu_addr = kiq->eop_gpu_addr;
ring->no_scheduler = true;
sprintf(ring->name, "kiq_%d.%d.%d.%d", xcc_id, ring->me, ring->pipe, ring->queue);
snprintf(ring->name, sizeof(ring->name), "kiq_%d.%d.%d.%d",
xcc_id, ring->me, ring->pipe, ring->queue);
r = amdgpu_ring_init(adev, ring, 1024, irq, AMDGPU_CP_KIQ_IRQ_DRIVER0,
AMDGPU_RING_PRIO_DEFAULT, NULL);
if (r)
+1 -5
View File
@@ -220,9 +220,6 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain)
placement->num_placement = c;
placement->placement = places;
placement->num_busy_placement = c;
placement->busy_placement = places;
}
/**
@@ -1397,8 +1394,7 @@ vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
AMDGPU_GEM_DOMAIN_GTT);
/* Avoid costly evictions; only set GTT as a busy placement */
abo->placement.num_busy_placement = 1;
abo->placement.busy_placement = &abo->placements[1];
abo->placements[0].flags |= TTM_PL_FLAG_DESIRED;
r = ttm_bo_validate(bo, &abo->placement, &ctx);
if (unlikely(r == -EBUSY || r == -ERESTARTSYS))
+2 -9
View File
@@ -102,23 +102,19 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo,
/* Don't handle scatter gather BOs */
if (bo->type == ttm_bo_type_sg) {
placement->num_placement = 0;
placement->num_busy_placement = 0;
return;
}
/* Object isn't an AMDGPU object so ignore */
if (!amdgpu_bo_is_amdgpu_bo(bo)) {
placement->placement = &placements;
placement->busy_placement = &placements;
placement->num_placement = 1;
placement->num_busy_placement = 1;
return;
}
abo = ttm_to_amdgpu_bo(bo);
if (abo->flags & AMDGPU_GEM_CREATE_DISCARDABLE) {
placement->num_placement = 0;
placement->num_busy_placement = 0;
return;
}
@@ -128,13 +124,13 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo,
case AMDGPU_PL_OA:
case AMDGPU_PL_DOORBELL:
placement->num_placement = 0;
placement->num_busy_placement = 0;
return;
case TTM_PL_VRAM:
if (!adev->mman.buffer_funcs_enabled) {
/* Move to system memory */
amdgpu_bo_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_CPU);
} else if (!amdgpu_gmc_vram_full_visible(&adev->gmc) &&
!(abo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) &&
amdgpu_bo_in_cpu_visible_vram(abo)) {
@@ -149,8 +145,7 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo,
AMDGPU_GEM_DOMAIN_CPU);
abo->placements[0].fpfn = adev->gmc.visible_vram_size >> PAGE_SHIFT;
abo->placements[0].lpfn = 0;
abo->placement.busy_placement = &abo->placements[1];
abo->placement.num_busy_placement = 1;
abo->placements[0].flags |= TTM_PL_FLAG_DESIRED;
} else {
/* Move to GTT memory */
amdgpu_bo_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_GTT |
@@ -966,8 +961,6 @@ int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo)
/* allocate GART space */
placement.num_placement = 1;
placement.placement = &placements;
placement.num_busy_placement = 1;
placement.busy_placement = &placements;
placements.fpfn = 0;
placements.lpfn = adev->gmc.gart_size >> PAGE_SHIFT;
placements.mem_type = TTM_PL_TT;
+6 -6
View File
@@ -230,14 +230,14 @@ static const struct drm_connector_funcs ch7033_connector_funcs = {
static int ch7033_connector_get_modes(struct drm_connector *connector)
{
struct ch7033_priv *priv = conn_to_ch7033_priv(connector);
struct edid *edid;
const struct drm_edid *drm_edid;
int ret;
edid = drm_bridge_get_edid(priv->next_bridge, connector);
drm_connector_update_edid_property(connector, edid);
if (edid) {
ret = drm_add_edid_modes(connector, edid);
kfree(edid);
drm_edid = drm_bridge_edid_read(priv->next_bridge, connector);
drm_edid_connector_update(connector, drm_edid);
if (drm_edid) {
ret = drm_edid_connector_add_modes(connector);
drm_edid_free(drm_edid);
} else {
ret = drm_add_modes_noedid(connector, 1920, 1080);
drm_set_preferred_mode(connector, 1024, 768);
+18
View File
@@ -3,6 +3,24 @@ if ARCH_MXC || COMPILE_TEST
config DRM_IMX_LDB_HELPER
tristate
config DRM_IMX8MP_DW_HDMI_BRIDGE
tristate "Freescale i.MX8MP HDMI-TX bridge support"
depends on OF
depends on COMMON_CLK
select DRM_DW_HDMI
select DRM_IMX8MP_HDMI_PVI
select PHY_FSL_SAMSUNG_HDMI_PHY
help
Choose this to enable support for the internal HDMI encoder found
on the i.MX8MP SoC.
config DRM_IMX8MP_HDMI_PVI
tristate "Freescale i.MX8MP HDMI PVI bridge support"
depends on OF
help
Choose this to enable support for the internal HDMI TX Parallel
Video Interface found on the Freescale i.MX8MP SoC.
config DRM_IMX8QM_LDB
tristate "Freescale i.MX8QM LVDS display bridge"
depends on OF
+2
View File
@@ -1,4 +1,6 @@
obj-$(CONFIG_DRM_IMX_LDB_HELPER) += imx-ldb-helper.o
obj-$(CONFIG_DRM_IMX8MP_DW_HDMI_BRIDGE) += imx8mp-hdmi-tx.o
obj-$(CONFIG_DRM_IMX8MP_HDMI_PVI) += imx8mp-hdmi-pvi.o
obj-$(CONFIG_DRM_IMX8QM_LDB) += imx8qm-ldb.o
obj-$(CONFIG_DRM_IMX8QXP_LDB) += imx8qxp-ldb.o
obj-$(CONFIG_DRM_IMX8QXP_PIXEL_COMBINER) += imx8qxp-pixel-combiner.o
@@ -0,0 +1,207 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2022 Pengutronix, Lucas Stach <kernel@pengutronix.de>
*/
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_crtc.h>
#include <linux/bitfield.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#define HTX_PVI_CTRL 0x0
#define PVI_CTRL_OP_VSYNC_POL BIT(18)
#define PVI_CTRL_OP_HSYNC_POL BIT(17)
#define PVI_CTRL_OP_DE_POL BIT(16)
#define PVI_CTRL_INP_VSYNC_POL BIT(14)
#define PVI_CTRL_INP_HSYNC_POL BIT(13)
#define PVI_CTRL_INP_DE_POL BIT(12)
#define PVI_CTRL_MODE_MASK GENMASK(2, 1)
#define PVI_CTRL_MODE_LCDIF 2
#define PVI_CTRL_EN BIT(0)
struct imx8mp_hdmi_pvi {
struct drm_bridge bridge;
struct device *dev;
struct drm_bridge *next_bridge;
void __iomem *regs;
};
static inline struct imx8mp_hdmi_pvi *
to_imx8mp_hdmi_pvi(struct drm_bridge *bridge)
{
return container_of(bridge, struct imx8mp_hdmi_pvi, bridge);
}
static int imx8mp_hdmi_pvi_bridge_attach(struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags)
{
struct imx8mp_hdmi_pvi *pvi = to_imx8mp_hdmi_pvi(bridge);
return drm_bridge_attach(bridge->encoder, pvi->next_bridge,
bridge, flags);
}
static void imx8mp_hdmi_pvi_bridge_enable(struct drm_bridge *bridge,
struct drm_bridge_state *bridge_state)
{
struct drm_atomic_state *state = bridge_state->base.state;
struct imx8mp_hdmi_pvi *pvi = to_imx8mp_hdmi_pvi(bridge);
struct drm_connector_state *conn_state;
const struct drm_display_mode *mode;
struct drm_crtc_state *crtc_state;
struct drm_connector *connector;
u32 bus_flags = 0, val;
connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
conn_state = drm_atomic_get_new_connector_state(state, connector);
crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
if (WARN_ON(pm_runtime_resume_and_get(pvi->dev)))
return;
mode = &crtc_state->adjusted_mode;
val = FIELD_PREP(PVI_CTRL_MODE_MASK, PVI_CTRL_MODE_LCDIF) | PVI_CTRL_EN;
if (mode->flags & DRM_MODE_FLAG_PVSYNC)
val |= PVI_CTRL_OP_VSYNC_POL | PVI_CTRL_INP_VSYNC_POL;
if (mode->flags & DRM_MODE_FLAG_PHSYNC)
val |= PVI_CTRL_OP_HSYNC_POL | PVI_CTRL_INP_HSYNC_POL;
if (pvi->next_bridge->timings)
bus_flags = pvi->next_bridge->timings->input_bus_flags;
else if (bridge_state)
bus_flags = bridge_state->input_bus_cfg.flags;
if (bus_flags & DRM_BUS_FLAG_DE_HIGH)
val |= PVI_CTRL_OP_DE_POL | PVI_CTRL_INP_DE_POL;
writel(val, pvi->regs + HTX_PVI_CTRL);
}
static void imx8mp_hdmi_pvi_bridge_disable(struct drm_bridge *bridge,
struct drm_bridge_state *bridge_state)
{
struct imx8mp_hdmi_pvi *pvi = to_imx8mp_hdmi_pvi(bridge);
writel(0x0, pvi->regs + HTX_PVI_CTRL);
pm_runtime_put(pvi->dev);
}
static u32 *
imx8mp_hdmi_pvi_bridge_get_input_bus_fmts(struct drm_bridge *bridge,
struct drm_bridge_state *bridge_state,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state,
u32 output_fmt,
unsigned int *num_input_fmts)
{
struct imx8mp_hdmi_pvi *pvi = to_imx8mp_hdmi_pvi(bridge);
struct drm_bridge *next_bridge = pvi->next_bridge;
struct drm_bridge_state *next_state;
if (!next_bridge->funcs->atomic_get_input_bus_fmts)
return NULL;
next_state = drm_atomic_get_new_bridge_state(crtc_state->state,
next_bridge);
return next_bridge->funcs->atomic_get_input_bus_fmts(next_bridge,
next_state,
crtc_state,
conn_state,
output_fmt,
num_input_fmts);
}
static const struct drm_bridge_funcs imx_hdmi_pvi_bridge_funcs = {
.attach = imx8mp_hdmi_pvi_bridge_attach,
.atomic_enable = imx8mp_hdmi_pvi_bridge_enable,
.atomic_disable = imx8mp_hdmi_pvi_bridge_disable,
.atomic_get_input_bus_fmts = imx8mp_hdmi_pvi_bridge_get_input_bus_fmts,
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
.atomic_reset = drm_atomic_helper_bridge_reset,
};
static int imx8mp_hdmi_pvi_probe(struct platform_device *pdev)
{
struct device_node *remote;
struct imx8mp_hdmi_pvi *pvi;
pvi = devm_kzalloc(&pdev->dev, sizeof(*pvi), GFP_KERNEL);
if (!pvi)
return -ENOMEM;
platform_set_drvdata(pdev, pvi);
pvi->dev = &pdev->dev;
pvi->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pvi->regs))
return PTR_ERR(pvi->regs);
/* Get the next bridge in the pipeline. */
remote = of_graph_get_remote_node(pdev->dev.of_node, 1, -1);
if (!remote)
return -EINVAL;
pvi->next_bridge = of_drm_find_bridge(remote);
of_node_put(remote);
if (!pvi->next_bridge)
return dev_err_probe(&pdev->dev, -EPROBE_DEFER,
"could not find next bridge\n");
pm_runtime_enable(&pdev->dev);
/* Register the bridge. */
pvi->bridge.funcs = &imx_hdmi_pvi_bridge_funcs;
pvi->bridge.of_node = pdev->dev.of_node;
pvi->bridge.timings = pvi->next_bridge->timings;
drm_bridge_add(&pvi->bridge);
return 0;
}
static int imx8mp_hdmi_pvi_remove(struct platform_device *pdev)
{
struct imx8mp_hdmi_pvi *pvi = platform_get_drvdata(pdev);
drm_bridge_remove(&pvi->bridge);
pm_runtime_disable(&pdev->dev);
return 0;
}
static const struct of_device_id imx8mp_hdmi_pvi_match[] = {
{
.compatible = "fsl,imx8mp-hdmi-pvi",
}, {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(of, imx8mp_hdmi_pvi_match);
static struct platform_driver imx8mp_hdmi_pvi_driver = {
.probe = imx8mp_hdmi_pvi_probe,
.remove = imx8mp_hdmi_pvi_remove,
.driver = {
.name = "imx-hdmi-pvi",
.of_match_table = imx8mp_hdmi_pvi_match,
},
};
module_platform_driver(imx8mp_hdmi_pvi_driver);
MODULE_DESCRIPTION("i.MX8MP HDMI TX Parallel Video Interface bridge driver");
MODULE_LICENSE("GPL");
+154
View File
@@ -0,0 +1,154 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2022 Pengutronix, Lucas Stach <kernel@pengutronix.de>
*/
#include <linux/clk.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <drm/bridge/dw_hdmi.h>
#include <drm/drm_modes.h>
struct imx8mp_hdmi {
struct dw_hdmi_plat_data plat_data;
struct dw_hdmi *dw_hdmi;
struct clk *pixclk;
};
static enum drm_mode_status
imx8mp_hdmi_mode_valid(struct dw_hdmi *dw_hdmi, void *data,
const struct drm_display_info *info,
const struct drm_display_mode *mode)
{
struct imx8mp_hdmi *hdmi = (struct imx8mp_hdmi *)data;
if (mode->clock < 13500)
return MODE_CLOCK_LOW;
if (mode->clock > 297000)
return MODE_CLOCK_HIGH;
if (clk_round_rate(hdmi->pixclk, mode->clock * 1000) !=
mode->clock * 1000)
return MODE_CLOCK_RANGE;
/* We don't support double-clocked and Interlaced modes */
if ((mode->flags & DRM_MODE_FLAG_DBLCLK) ||
(mode->flags & DRM_MODE_FLAG_INTERLACE))
return MODE_BAD;
return MODE_OK;
}
static int imx8mp_hdmi_phy_init(struct dw_hdmi *dw_hdmi, void *data,
const struct drm_display_info *display,
const struct drm_display_mode *mode)
{
return 0;
}
static void imx8mp_hdmi_phy_disable(struct dw_hdmi *dw_hdmi, void *data)
{
}
static void im8mp_hdmi_phy_setup_hpd(struct dw_hdmi *hdmi, void *data)
{
/*
* Just release PHY core from reset, all other power management is done
* by the PHY driver.
*/
dw_hdmi_phy_gen1_reset(hdmi);
dw_hdmi_phy_setup_hpd(hdmi, data);
}
static const struct dw_hdmi_phy_ops imx8mp_hdmi_phy_ops = {
.init = imx8mp_hdmi_phy_init,
.disable = imx8mp_hdmi_phy_disable,
.setup_hpd = im8mp_hdmi_phy_setup_hpd,
.read_hpd = dw_hdmi_phy_read_hpd,
.update_hpd = dw_hdmi_phy_update_hpd,
};
static int imx8mp_dw_hdmi_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct dw_hdmi_plat_data *plat_data;
struct imx8mp_hdmi *hdmi;
hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
if (!hdmi)
return -ENOMEM;
plat_data = &hdmi->plat_data;
hdmi->pixclk = devm_clk_get(dev, "pix");
if (IS_ERR(hdmi->pixclk))
return dev_err_probe(dev, PTR_ERR(hdmi->pixclk),
"Unable to get pixel clock\n");
plat_data->mode_valid = imx8mp_hdmi_mode_valid;
plat_data->phy_ops = &imx8mp_hdmi_phy_ops;
plat_data->phy_name = "SAMSUNG HDMI TX PHY";
plat_data->priv_data = hdmi;
plat_data->phy_force_vendor = true;
hdmi->dw_hdmi = dw_hdmi_probe(pdev, plat_data);
if (IS_ERR(hdmi->dw_hdmi))
return PTR_ERR(hdmi->dw_hdmi);
platform_set_drvdata(pdev, hdmi);
return 0;
}
static int imx8mp_dw_hdmi_remove(struct platform_device *pdev)
{
struct imx8mp_hdmi *hdmi = platform_get_drvdata(pdev);
dw_hdmi_remove(hdmi->dw_hdmi);
return 0;
}
static int __maybe_unused imx8mp_dw_hdmi_pm_suspend(struct device *dev)
{
return 0;
}
static int __maybe_unused imx8mp_dw_hdmi_pm_resume(struct device *dev)
{
struct imx8mp_hdmi *hdmi = dev_get_drvdata(dev);
dw_hdmi_resume(hdmi->dw_hdmi);
return 0;
}
static const struct dev_pm_ops imx8mp_dw_hdmi_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(imx8mp_dw_hdmi_pm_suspend,
imx8mp_dw_hdmi_pm_resume)
};
static const struct of_device_id imx8mp_dw_hdmi_of_table[] = {
{ .compatible = "fsl,imx8mp-hdmi-tx" },
{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(of, imx8mp_dw_hdmi_of_table);
static struct platform_driver imx8mp_dw_hdmi_platform_driver = {
.probe = imx8mp_dw_hdmi_probe,
.remove = imx8mp_dw_hdmi_remove,
.driver = {
.name = "imx8mp-dw-hdmi-tx",
.of_match_table = imx8mp_dw_hdmi_of_table,
.pm = &imx8mp_dw_hdmi_pm_ops,
},
};
module_platform_driver(imx8mp_dw_hdmi_platform_driver);
MODULE_DESCRIPTION("i.MX8MP HDMI encoder driver");
MODULE_LICENSE("GPL");
+10 -10
View File
@@ -440,16 +440,16 @@ lt8912_connector_mode_valid(struct drm_connector *connector,
static int lt8912_connector_get_modes(struct drm_connector *connector)
{
struct edid *edid;
const struct drm_edid *drm_edid;
int ret = -1;
int num = 0;
struct lt8912 *lt = connector_to_lt8912(connector);
u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
edid = drm_bridge_get_edid(lt->hdmi_port, connector);
if (edid) {
drm_connector_update_edid_property(connector, edid);
num = drm_add_edid_modes(connector, edid);
drm_edid = drm_bridge_edid_read(lt->hdmi_port, connector);
drm_edid_connector_update(connector, drm_edid);
if (drm_edid) {
num = drm_edid_connector_add_modes(connector);
} else {
return ret;
}
@@ -459,7 +459,7 @@ static int lt8912_connector_get_modes(struct drm_connector *connector)
if (ret)
num = ret;
kfree(edid);
drm_edid_free(drm_edid);
return num;
}
@@ -620,8 +620,8 @@ lt8912_bridge_detect(struct drm_bridge *bridge)
return lt8912_check_cable_status(lt);
}
static struct edid *lt8912_bridge_get_edid(struct drm_bridge *bridge,
struct drm_connector *connector)
static const struct drm_edid *lt8912_bridge_edid_read(struct drm_bridge *bridge,
struct drm_connector *connector)
{
struct lt8912 *lt = bridge_to_lt8912(bridge);
@@ -630,7 +630,7 @@ static struct edid *lt8912_bridge_get_edid(struct drm_bridge *bridge,
* given to the hdmi connector node.
*/
if (lt->hdmi_port->ops & DRM_BRIDGE_OP_EDID)
return drm_bridge_get_edid(lt->hdmi_port, connector);
return drm_bridge_edid_read(lt->hdmi_port, connector);
dev_warn(lt->dev, "The connected bridge does not supports DRM_BRIDGE_OP_EDID\n");
return NULL;
@@ -642,7 +642,7 @@ static const struct drm_bridge_funcs lt8912_bridge_funcs = {
.mode_set = lt8912_bridge_mode_set,
.enable = lt8912_bridge_enable,
.detect = lt8912_bridge_detect,
.get_edid = lt8912_bridge_get_edid,
.edid_read = lt8912_bridge_edid_read,
};
static int lt8912_bridge_resume(struct device *dev)
+1
View File
@@ -18,6 +18,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_edid.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_of.h>
#include <drm/drm_print.h>
+6 -5
View File
@@ -21,6 +21,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_edid.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
@@ -294,12 +295,12 @@ static int lt9611uxc_connector_get_modes(struct drm_connector *connector)
{
struct lt9611uxc *lt9611uxc = connector_to_lt9611uxc(connector);
unsigned int count;
struct edid *edid;
const struct drm_edid *drm_edid;
edid = drm_bridge_get_edid(&lt9611uxc->bridge, connector);
drm_connector_update_edid_property(connector, edid);
count = drm_add_edid_modes(connector, edid);
kfree(edid);
drm_edid = drm_bridge_edid_read(&lt9611uxc->bridge, connector);
drm_edid_connector_update(connector, drm_edid);
count = drm_edid_connector_add_modes(connector);
drm_edid_free(drm_edid);
return count;
}
+7 -3
View File
@@ -96,6 +96,7 @@
#define DSIM_MFLUSH_VS BIT(29)
/* This flag is valid only for exynos3250/3472/5260/5430 */
#define DSIM_CLKLANE_STOP BIT(30)
#define DSIM_NON_CONTINUOUS_CLKLANE BIT(31)
/* DSIM_ESCMODE */
#define DSIM_TX_TRIGGER_RST BIT(4)
@@ -945,8 +946,12 @@ static int samsung_dsim_init_link(struct samsung_dsim *dsi)
* power consumption.
*/
if (driver_data->has_clklane_stop &&
dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)
dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) {
if (!samsung_dsim_hw_is_exynos(dsi->plat_data->hw_type))
reg |= DSIM_NON_CONTINUOUS_CLKLANE;
reg |= DSIM_CLKLANE_STOP;
}
samsung_dsim_write(dsi, DSIM_CONFIG_REG, reg);
lanes_mask = BIT(dsi->lanes) - 1;
@@ -1498,6 +1503,7 @@ static void samsung_dsim_atomic_disable(struct drm_bridge *bridge,
if (!(dsi->state & DSIM_STATE_ENABLED))
return;
samsung_dsim_set_display_enable(dsi, false);
dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE;
}
@@ -1506,8 +1512,6 @@ static void samsung_dsim_atomic_post_disable(struct drm_bridge *bridge,
{
struct samsung_dsim *dsi = bridge_to_dsi(bridge);
samsung_dsim_set_display_enable(dsi, false);
dsi->state &= ~DSIM_STATE_ENABLED;
pm_runtime_put_sync(dsi->dev);
}
+9 -8
View File
@@ -51,18 +51,20 @@ drm_connector_to_simple_bridge(struct drm_connector *connector)
static int simple_bridge_get_modes(struct drm_connector *connector)
{
struct simple_bridge *sbridge = drm_connector_to_simple_bridge(connector);
struct edid *edid;
const struct drm_edid *drm_edid;
int ret;
if (sbridge->next_bridge->ops & DRM_BRIDGE_OP_EDID) {
edid = drm_bridge_get_edid(sbridge->next_bridge, connector);
if (!edid)
drm_edid = drm_bridge_edid_read(sbridge->next_bridge, connector);
if (!drm_edid)
DRM_INFO("EDID read failed. Fallback to standard modes\n");
} else {
edid = NULL;
drm_edid = NULL;
}
if (!edid) {
drm_edid_connector_update(connector, drm_edid);
if (!drm_edid) {
/*
* In case we cannot retrieve the EDIDs (missing or broken DDC
* bus from the next bridge), fallback on the XGA standards and
@@ -73,9 +75,8 @@ static int simple_bridge_get_modes(struct drm_connector *connector)
return ret;
}
drm_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid);
kfree(edid);
ret = drm_edid_connector_add_modes(connector);
drm_edid_free(drm_edid);
return ret;
}
@@ -31,6 +31,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_edid.h>
#include <drm/drm_of.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
+6 -1
View File
@@ -617,9 +617,14 @@ static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock)
continue;
for (i_post = 0; i_post < ARRAY_SIZE(ext_div); i_post++) {
for (div = 1; div <= 16; div++) {
u32 clk;
u32 clk, iclk;
u64 tmp;
/* PCLK PLL input unit clock ... 6..40 MHz */
iclk = refclk / (div * ext_div[i_pre]);
if (iclk < 6000000 || iclk > 40000000)
continue;
tmp = pixelclock * ext_div[i_pre] *
ext_div[i_post] * div;
do_div(tmp, refclk);
+9 -9
View File
@@ -50,18 +50,20 @@ drm_connector_to_tfp410(struct drm_connector *connector)
static int tfp410_get_modes(struct drm_connector *connector)
{
struct tfp410 *dvi = drm_connector_to_tfp410(connector);
struct edid *edid;
const struct drm_edid *drm_edid;
int ret;
if (dvi->next_bridge->ops & DRM_BRIDGE_OP_EDID) {
edid = drm_bridge_get_edid(dvi->next_bridge, connector);
if (!edid)
drm_edid = drm_bridge_edid_read(dvi->next_bridge, connector);
if (!drm_edid)
DRM_INFO("EDID read failed. Fallback to standard modes\n");
} else {
edid = NULL;
drm_edid = NULL;
}
if (!edid) {
drm_edid_connector_update(connector, drm_edid);
if (!drm_edid) {
/*
* No EDID, fallback on the XGA standard modes and prefer a mode
* pretty much anything can handle.
@@ -71,11 +73,9 @@ static int tfp410_get_modes(struct drm_connector *connector)
return ret;
}
drm_connector_update_edid_property(connector, edid);
ret = drm_edid_connector_add_modes(connector);
ret = drm_add_edid_modes(connector, edid);
kfree(edid);
drm_edid_free(drm_edid);
return ret;
}
+1
View File
@@ -26,6 +26,7 @@ if [[ "$KERNEL_ARCH" = "arm64" ]]; then
DEVICE_TREES+=" arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-juniper-sku16.dtb"
DEVICE_TREES+=" arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dtb"
DEVICE_TREES+=" arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor-limozeen-nots-r5.dtb"
DEVICE_TREES+=" arch/arm64/boot/dts/qcom/sc7180-trogdor-kingoftown.dtb"
elif [[ "$KERNEL_ARCH" = "arm" ]]; then
GCC_ARCH="arm-linux-gnueabihf"
DEBIAN_ARCH="armhf"
+12 -2
View File
@@ -1,6 +1,6 @@
variables:
DRM_CI_PROJECT_PATH: &drm-ci-project-path mesa/mesa
DRM_CI_COMMIT_SHA: &drm-ci-commit-sha edfbf74df1d4d6ce54ffe24566108be0e1a98c3d
DRM_CI_COMMIT_SHA: &drm-ci-commit-sha 9d162de9a05155e1c4041857a5848842749164cf
UPSTREAM_REPO: git://anongit.freedesktop.org/drm/drm
TARGET_BRANCH: drm-next
@@ -25,7 +25,9 @@ variables:
# per-job artifact storage on MinIO
JOB_ARTIFACTS_BASE: ${PIPELINE_ARTIFACTS_BASE}/${CI_JOB_ID}
# default kernel for rootfs before injecting the current kernel tree
KERNEL_IMAGE_BASE: https://${S3_HOST}/mesa-lava/gfx-ci/linux/v6.4.12-for-mesa-ci-f6b4ad45f48d
KERNEL_REPO: "gfx-ci/linux"
KERNEL_TAG: "v6.6.4-for-mesa-ci-e4f4c500f7fb"
KERNEL_IMAGE_BASE: https://${S3_HOST}/mesa-lava/${KERNEL_REPO}/${KERNEL_TAG}
LAVA_TAGS: subset-1-gfx
LAVA_JOB_PRIORITY: 30
@@ -133,6 +135,11 @@ stages:
- if: &is-pre-merge-for-marge '$GITLAB_USER_LOGIN == "marge-bot" && $CI_PIPELINE_SOURCE == "merge_request_event"'
when: on_success
.never-post-merge-rules:
rules:
- if: *is-post-merge
when: never
# Rule to filter for only scheduled pipelines.
.scheduled_pipeline-rules:
rules:
@@ -150,6 +157,7 @@ stages:
.build-rules:
rules:
- !reference [.no_scheduled_pipelines-rules, rules]
- !reference [.never-post-merge-rules, rules]
# Run automatically once all dependency jobs have passed
- when: on_success
@@ -157,6 +165,7 @@ stages:
.container+build-rules:
rules:
- !reference [.no_scheduled_pipelines-rules, rules]
- !reference [.never-post-merge-rules, rules]
- when: manual
.ci-deqp-artifacts:
@@ -175,6 +184,7 @@ stages:
.container-rules:
rules:
- !reference [.no_scheduled_pipelines-rules, rules]
- !reference [.never-post-merge-rules, rules]
# Run pipeline by default in the main project if any CI pipeline
# configuration files were changed, to ensure docker images are up to date
- if: *is-post-merge
+21 -5
View File
@@ -82,20 +82,35 @@
tags:
- $RUNNER_TAG
msm:sc7180:
.msm-sc7180:
extends:
- .lava-igt:arm64
stage: msm
parallel: 4
variables:
DRIVER_NAME: msm
DEVICE_TYPE: sc7180-trogdor-lazor-limozeen
DTB: sc7180-trogdor-lazor-limozeen-nots-r5
BOOT_METHOD: depthcharge
KERNEL_IMAGE_TYPE: ""
GPU_VERSION: sc7180
msm:sc7180-trogdor-lazor-limozeen:
extends:
- .msm-sc7180
parallel: 4
variables:
DEVICE_TYPE: sc7180-trogdor-lazor-limozeen
DTB: sc7180-trogdor-lazor-limozeen-nots-r5
GPU_VERSION: ${DEVICE_TYPE}
RUNNER_TAG: mesa-ci-x86-64-lava-sc7180-trogdor-lazor-limozeen
msm:sc7180-trogdor-kingoftown:
extends:
- .msm-sc7180
parallel: 6
variables:
DEVICE_TYPE: sc7180-trogdor-kingoftown
DTB: sc7180-trogdor-kingoftown
GPU_VERSION: ${DEVICE_TYPE}
RUNNER_TAG: mesa-ci-x86-64-lava-sc7180-trogdor-kingoftown
msm:apq8016:
extends:
- .baremetal-igt-arm64
@@ -324,6 +339,7 @@ virtio_gpu:none:
GPU_VERSION: none
extends:
- .test-gl
- .test-rules
tags:
- kvm
script:
+49
View File
@@ -2910,3 +2910,52 @@ kms_writeback@writeback-invalid-parameters
kms_writeback@writeback-fb-id
kms_writeback@writeback-check-output
prime_mmap_kms@buffer-sharing
msm_shrink@copy-gpu-sanitycheck-8
msm_shrink@copy-gpu-sanitycheck-32
msm_shrink@copy-gpu-8
msm_shrink@copy-gpu-32
msm_shrink@copy-gpu-madvise-8
msm_shrink@copy-gpu-madvise-32
msm_shrink@copy-gpu-oom-8
msm_shrink@copy-gpu-oom-32
msm_shrink@copy-mmap-sanitycheck-8
msm_shrink@copy-mmap-sanitycheck-32
msm_shrink@copy-mmap-8
msm_shrink@copy-mmap-32
msm_shrink@copy-mmap-madvise-8
msm_shrink@copy-mmap-madvise-32
msm_shrink@copy-mmap-oom-8
msm_shrink@copy-mmap-oom-32
msm_shrink@copy-mmap-dmabuf-sanitycheck-8
msm_shrink@copy-mmap-dmabuf-sanitycheck-32
msm_shrink@copy-mmap-dmabuf-8
msm_shrink@copy-mmap-dmabuf-32
msm_shrink@copy-mmap-dmabuf-madvise-8
msm_shrink@copy-mmap-dmabuf-madvise-32
msm_shrink@copy-mmap-dmabuf-oom-8
msm_shrink@copy-mmap-dmabuf-oom-32
msm_mapping@ring
msm_mapping@sqefw
msm_mapping@shadow
msm_submitoverhead@submitbench-10-bos
msm_submitoverhead@submitbench-10-bos-no-implicit-sync
msm_submitoverhead@submitbench-100-bos
msm_submitoverhead@submitbench-100-bos-no-implicit-sync
msm_submitoverhead@submitbench-250-bos
msm_submitoverhead@submitbench-250-bos-no-implicit-sync
msm_submitoverhead@submitbench-500-bos
msm_submitoverhead@submitbench-500-bos-no-implicit-sync
msm_submitoverhead@submitbench-1000-bos
msm_submitoverhead@submitbench-1000-bos-no-implicit-sync
msm_recovery@hangcheck
msm_recovery@gpu-fault
msm_recovery@gpu-fault-parallel
msm_recovery@iova-fault
msm_submit@empty-submit
msm_submit@invalid-queue-submit
msm_submit@invalid-flags-submit
msm_submit@invalid-in-fence-submit
msm_submit@invalid-duplicate-bo-submit
msm_submit@invalid-cmd-idx-submit
msm_submit@invalid-cmd-type-submit
msm_submit@valid-submit
@@ -6,8 +6,6 @@ kms_cursor_legacy@all-pipes-single-bo,Fail
kms_cursor_legacy@all-pipes-single-move,Fail
kms_cursor_legacy@all-pipes-torture-bo,Fail
kms_cursor_legacy@all-pipes-torture-move,Fail
kms_cursor_legacy@forked-bo,Fail
kms_cursor_legacy@forked-move,Fail
kms_cursor_legacy@pipe-A-forked-bo,Fail
kms_cursor_legacy@pipe-A-forked-move,Fail
kms_cursor_legacy@pipe-A-single-bo,Fail
@@ -18,3 +16,4 @@ kms_force_connector_basic@force-edid,Fail
kms_hdmi_inject@inject-4k,Fail
kms_selftest@drm_format,Timeout
kms_selftest@drm_format_helper,Timeout
msm_mapping@ring,Fail
@@ -1,30 +0,0 @@
kms_color@ctm-0-25,Fail
kms_color@ctm-0-50,Fail
kms_color@ctm-0-75,Fail
kms_color@ctm-blue-to-red,Fail
kms_color@ctm-green-to-red,Fail
kms_color@ctm-negative,Fail
kms_color@ctm-red-to-blue,Fail
kms_color@ctm-signed,Fail
kms_cursor_legacy@cursor-vs-flip-toggle,Fail
kms_cursor_legacy@cursor-vs-flip-varying-size,Fail
kms_cursor_legacy@cursorA-vs-flipA-atomic-transitions,Crash
kms_flip@flip-vs-modeset-vs-hang,Fail
kms_flip@flip-vs-panning-vs-hang,Fail
kms_pipe_crc_basic@compare-crc-sanitycheck-nv12,Fail
kms_plane_alpha_blend@alpha-7efc,Fail
kms_plane_alpha_blend@coverage-7efc,Fail
kms_plane_alpha_blend@coverage-vs-premult-vs-constant,Fail
kms_plane_alpha_blend@pipe-A-alpha-7efc,Fail
kms_plane_alpha_blend@pipe-A-coverage-7efc,Fail
kms_plane_alpha_blend@pipe-A-coverage-vs-premult-vs-constant,Fail
kms_plane_alpha_blend@pipe-B-alpha-7efc,Fail
kms_plane_alpha_blend@pipe-B-alpha-basic,Fail
kms_plane_alpha_blend@pipe-B-alpha-opaque-fb,Fail
kms_plane_alpha_blend@pipe-B-constant-alpha-max,Fail
kms_plane_alpha_blend@pipe-B-constant-alpha-mid,Fail
kms_plane_alpha_blend@pipe-B-coverage-7efc,Fail
kms_plane_alpha_blend@pipe-B-coverage-vs-premult-vs-constant,Fail
kms_rmfb@close-fd,Fail
kms_universal_plane@disable-primary-vs-flip-pipe-b,Fail
kms_universal_plane@universal-plane-pipe-B-sanity,Fail
@@ -1,17 +0,0 @@
kms_color@ctm-0-25
kms_color@ctm-0-50
kms_color@ctm-0-75
kms_color@ctm-blue-to-red
kms_color@ctm-green-to-red
kms_color@ctm-negative
kms_color@ctm-red-to-blue
kms_color@ctm-signed
kms_flip@flip-vs-modeset-vs-hang
kms_flip@flip-vs-panning-vs-hang
kms_plane@pixel-format
kms_plane@pixel-format-source-clamping
kms_plane@plane-position-covered
kms_plane@plane-position-hole
kms_plane@plane-position-hole-dpms
kms_writeback@writeback-fb-id
kms_writeback@writeback-invalid-parameters
@@ -1,7 +0,0 @@
# Suspend to RAM seems to be broken on this machine
.*suspend.*
# Test incorrectly assumes that CTM support implies gamma/degamma
# LUT support. None of the subtests handle the case of only having
# CTM support
#kms_color.*
@@ -0,0 +1,17 @@
kms_color@ctm-0-25,Fail
kms_color@ctm-0-50,Fail
kms_color@ctm-0-75,Fail
kms_color@ctm-blue-to-red,Fail
kms_color@ctm-green-to-red,Fail
kms_color@ctm-negative,Fail
kms_color@ctm-red-to-blue,Fail
kms_color@ctm-signed,Fail
kms_cursor_legacy@cursor-vs-flip-toggle,Fail
kms_cursor_legacy@cursor-vs-flip-varying-size,Fail
kms_flip@flip-vs-modeset-vs-hang,Fail
kms_flip@flip-vs-panning-vs-hang,Fail
kms_pipe_crc_basic@compare-crc-sanitycheck-nv12,Fail
kms_plane_alpha_blend@alpha-7efc,Fail
kms_plane_alpha_blend@coverage-7efc,Fail
kms_plane_alpha_blend@coverage-vs-premult-vs-constant,Fail
kms_rmfb@close-fd,Fail
@@ -0,0 +1,17 @@
kms_color@ctm-0-25,Fail
kms_color@ctm-0-50,Fail
kms_color@ctm-0-75,Fail
kms_color@ctm-blue-to-red,Fail
kms_color@ctm-green-to-red,Fail
kms_color@ctm-negative,Fail
kms_color@ctm-red-to-blue,Fail
kms_color@ctm-signed,Fail
kms_cursor_legacy@cursor-vs-flip-toggle,Fail
kms_cursor_legacy@cursor-vs-flip-varying-size,Fail
kms_flip@flip-vs-modeset-vs-hang,Fail
kms_flip@flip-vs-panning-vs-hang,Fail
kms_pipe_crc_basic@compare-crc-sanitycheck-nv12,Fail
kms_plane_alpha_blend@alpha-7efc,Fail
kms_plane_alpha_blend@coverage-7efc,Fail
kms_plane_alpha_blend@coverage-vs-premult-vs-constant,Fail
kms_rmfb@close-fd,Fail
@@ -15,7 +15,7 @@ kms_color@pipe-A-ctm-max,Fail
kms_color@pipe-A-ctm-negative,Fail
kms_color@pipe-A-ctm-red-to-blue,Fail
kms_color@pipe-A-legacy-gamma,Fail
kms_cursor_legacy@basic-flip-after-cursor-legacy,Fail
kms_cursor_legacy@basic-flip-after-cursor-atomic,Fail
kms_cursor_legacy@basic-flip-after-cursor-varying-size,Fail
kms_cursor_legacy@basic-flip-before-cursor-atomic,Fail
kms_cursor_legacy@basic-flip-before-cursor-legacy,Fail
@@ -29,9 +29,6 @@ kms_cursor_legacy@flip-vs-cursor-atomic,Fail
kms_cursor_legacy@flip-vs-cursor-crc-atomic,Fail
kms_cursor_legacy@flip-vs-cursor-crc-legacy,Fail
kms_cursor_legacy@flip-vs-cursor-legacy,Fail
kms_cursor_legacy@short-flip-after-cursor-atomic-transitions,Fail
kms_cursor_legacy@short-flip-after-cursor-atomic-transitions-varying-size,Fail
kms_cursor_legacy@short-flip-after-cursor-toggle,Fail
kms_flip@flip-vs-modeset-vs-hang,Fail
kms_flip@flip-vs-panning-vs-hang,Fail
kms_pipe_crc_basic@compare-crc-sanitycheck-nv12,Fail
@@ -1,12 +1,22 @@
kms_cursor_legacy@basic-flip-after-cursor-atomic
kms_cursor_legacy@basic-flip-before-cursor-varying-size
kms_cursor_legacy@cursorA-vs-flipA-toggle
kms_cursor_legacy@flip-vs-cursor-atomic-transitions
# Board Name: msm:sdm845
# Bug Report: https://lore.kernel.org/dri-devel/46287831-edfa-78e8-6055-d7a08831c445@collabora.com/T/#u
# Failure Rate: 50
# IGT Version: 1.28-gd2af13d9f
# Linux Version: 6.7.0-rc3
# Reported by deqp-runner
kms_cursor_legacy@basic-flip-after-cursor-legacy
kms_cursor_legacy@flip-vs-cursor-toggle
kms_cursor_legacy@flip-vs-cursor-varying-size
kms_cursor_legacy@short-flip-after-cursor-toggle
kms_cursor_legacy@short-flip-before-cursor-atomic-transitions
kms_cursor_legacy@short-flip-before-cursor-toggle
kms_flip@flip-vs-modeset-vs-hang
kms_flip@flip-vs-panning-vs-hang
kms_plane@pixel-format
kms_plane@pixel-format-source-clamping
kms_cursor_legacy@short-flip-before-cursor-atomic-transitions-varying-size
msm_shrink@copy-gpu-32
msm_shrink@copy-gpu-oom-32
# The below test shows inconsistency across multiple runs, giving
# results of Pass and Fail alternately.
kms_cursor_legacy@basic-flip-before-cursor-varying-size
kms_cursor_legacy@flip-vs-cursor-atomic-transitions
kms_cursor_legacy@short-flip-after-cursor-atomic-transitions
kms_cursor_legacy@short-flip-after-cursor-atomic-transitions-varying-size
@@ -1,2 +1,7 @@
# Hangs machine
kms_bw.*
kms_bw.*
# Failing due to a bootloader/fw issue. The workaround in mesa CI involves these two patches
# https://gitlab.freedesktop.org/gfx-ci/linux/-/commit/4b49f902ec6f2bb382cbbf489870573f4b43371e
# https://gitlab.freedesktop.org/gfx-ci/linux/-/commit/38cdf4c5559771e2474ae0fecef8469f65147bc1
msm_mapping@*
+1 -1
View File
@@ -127,7 +127,7 @@ static void dp_aux_ep_shutdown(struct device *dev)
aux_ep_drv->shutdown(to_dp_aux_ep_dev(dev));
}
static struct bus_type dp_aux_bus_type = {
static const struct bus_type dp_aux_bus_type = {
.name = "dp-aux",
.match = dp_aux_ep_match,
.probe = dp_aux_ep_probe,
+28 -8
View File
@@ -27,8 +27,9 @@
#include <linux/mutex.h>
#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_debugfs.h>
#include <drm/drm_bridge.h>
#include <drm/drm_debugfs.h>
#include <drm/drm_edid.h>
#include <drm/drm_encoder.h>
#include <drm/drm_file.h>
#include <drm/drm_of.h>
@@ -1207,26 +1208,45 @@ int drm_bridge_get_modes(struct drm_bridge *bridge,
EXPORT_SYMBOL_GPL(drm_bridge_get_modes);
/**
* drm_bridge_get_edid - get the EDID data of the connected display
* drm_bridge_edid_read - read the EDID data of the connected display
* @bridge: bridge control structure
* @connector: the connector to read EDID for
*
* If the bridge supports output EDID retrieval, as reported by the
* DRM_BRIDGE_OP_EDID bridge ops flag, call &drm_bridge_funcs.get_edid to
* get the EDID and return it. Otherwise return NULL.
* DRM_BRIDGE_OP_EDID bridge ops flag, call &drm_bridge_funcs.edid_read to get
* the EDID and return it. Otherwise return NULL.
*
* If &drm_bridge_funcs.edid_read is not set, fall back to using
* &drm_bridge_funcs.get_edid and wrapping it in struct drm_edid.
*
* RETURNS:
* The retrieved EDID on success, or NULL otherwise.
*/
struct edid *drm_bridge_get_edid(struct drm_bridge *bridge,
struct drm_connector *connector)
const struct drm_edid *drm_bridge_edid_read(struct drm_bridge *bridge,
struct drm_connector *connector)
{
if (!(bridge->ops & DRM_BRIDGE_OP_EDID))
return NULL;
return bridge->funcs->get_edid(bridge, connector);
/* Transitional: Fall back to ->get_edid. */
if (!bridge->funcs->edid_read) {
const struct drm_edid *drm_edid;
struct edid *edid;
edid = bridge->funcs->get_edid(bridge, connector);
if (!edid)
return NULL;
drm_edid = drm_edid_alloc(edid, (edid->extensions + 1) * EDID_LENGTH);
kfree(edid);
return drm_edid;
}
return bridge->funcs->edid_read(bridge, connector);
}
EXPORT_SYMBOL_GPL(drm_bridge_get_edid);
EXPORT_SYMBOL_GPL(drm_bridge_edid_read);
/**
* drm_bridge_hpd_enable - enable hot plug detection for the bridge
+8 -8
View File
@@ -239,27 +239,27 @@ static int drm_bridge_connector_get_modes_edid(struct drm_connector *connector,
struct drm_bridge *bridge)
{
enum drm_connector_status status;
struct edid *edid;
const struct drm_edid *drm_edid;
int n;
status = drm_bridge_connector_detect(connector, false);
if (status != connector_status_connected)
goto no_edid;
edid = drm_bridge_get_edid(bridge, connector);
if (!drm_edid_is_valid(edid)) {
kfree(edid);
drm_edid = drm_bridge_edid_read(bridge, connector);
if (!drm_edid_valid(drm_edid)) {
drm_edid_free(drm_edid);
goto no_edid;
}
drm_connector_update_edid_property(connector, edid);
n = drm_add_edid_modes(connector, edid);
drm_edid_connector_update(connector, drm_edid);
n = drm_edid_connector_add_modes(connector);
kfree(edid);
drm_edid_free(drm_edid);
return n;
no_edid:
drm_connector_update_edid_property(connector, NULL);
drm_edid_connector_update(connector, NULL);
return 0;
}
+1 -1
View File
@@ -76,7 +76,7 @@ static void drm_exec_unlock_all(struct drm_exec *exec)
* If nr is non-zero then it is used as the initial objects table size.
* In either case, the table will grow (be re-allocated) on demand.
*/
void drm_exec_init(struct drm_exec *exec, uint32_t flags, unsigned nr)
void drm_exec_init(struct drm_exec *exec, u32 flags, unsigned nr)
{
if (!nr)
nr = PAGE_SIZE / sizeof(void *);
-2
View File
@@ -147,7 +147,6 @@ static void drm_gem_vram_placement(struct drm_gem_vram_object *gbo,
invariant_flags = TTM_PL_FLAG_TOPDOWN;
gbo->placement.placement = gbo->placements;
gbo->placement.busy_placement = gbo->placements;
if (pl_flag & DRM_GEM_VRAM_PL_FLAG_VRAM) {
gbo->placements[c].mem_type = TTM_PL_VRAM;
@@ -160,7 +159,6 @@ static void drm_gem_vram_placement(struct drm_gem_vram_object *gbo,
}
gbo->placement.num_placement = c;
gbo->placement.num_busy_placement = c;
for (i = 0; i < c; ++i) {
gbo->placements[i].fpfn = 0;
+39
View File
@@ -176,6 +176,45 @@ int __drmm_add_action_or_reset(struct drm_device *dev,
}
EXPORT_SYMBOL(__drmm_add_action_or_reset);
/**
* drmm_release_action - release a managed action from a &drm_device
* @dev: DRM device
* @action: function which would be called when @dev is released
* @data: opaque pointer, passed to @action
*
* This function calls the @action previously added by drmm_add_action()
* immediately.
* The @action is removed from the list of cleanup actions for @dev,
* which means that it won't be called in the final drm_dev_put().
*/
void drmm_release_action(struct drm_device *dev,
drmres_release_t action,
void *data)
{
struct drmres *dr_match = NULL, *dr;
unsigned long flags;
spin_lock_irqsave(&dev->managed.lock, flags);
list_for_each_entry_reverse(dr, &dev->managed.resources, node.entry) {
if (dr->node.release == action) {
if (!data || (data && *(void **)dr->data == data)) {
dr_match = dr;
del_dr(dev, dr_match);
break;
}
}
}
spin_unlock_irqrestore(&dev->managed.lock, flags);
if (WARN_ON(!dr_match))
return;
action(dev, data);
free_dr(dr_match);
}
EXPORT_SYMBOL(drmm_release_action);
/**
* drmm_kmalloc - &drm_device managed kmalloc()
* @dev: DRM device
+1 -1
View File
@@ -89,7 +89,7 @@ static const struct dev_pm_ops mipi_dsi_device_pm_ops = {
.restore = pm_generic_restore,
};
static struct bus_type mipi_dsi_bus_type = {
static const struct bus_type mipi_dsi_bus_type = {
.name = "mipi-dsi",
.match = mipi_dsi_device_match,
.uevent = mipi_dsi_uevent,
@@ -117,6 +117,12 @@ static const struct drm_dmi_panel_orientation_data lcd1080x1920_leftside_up = {
.orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP,
};
static const struct drm_dmi_panel_orientation_data lcd1080x1920_rightside_up = {
.width = 1080,
.height = 1920,
.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
};
static const struct drm_dmi_panel_orientation_data lcd1200x1920_rightside_up = {
.width = 1200,
.height = 1920,
@@ -279,6 +285,12 @@ static const struct dmi_system_id orientation_data[] = {
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "G1618-03")
},
.driver_data = (void *)&lcd720x1280_rightside_up,
}, { /* GPD Win Mini */
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "G1617-01")
},
.driver_data = (void *)&lcd1080x1920_rightside_up,
}, { /* I.T.Works TW891 */
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."),
+15 -22
View File
@@ -65,8 +65,6 @@ static const struct ttm_place sys_placement_flags = {
static struct ttm_placement i915_sys_placement = {
.num_placement = 1,
.placement = &sys_placement_flags,
.num_busy_placement = 1,
.busy_placement = &sys_placement_flags,
};
/**
@@ -157,32 +155,28 @@ i915_ttm_place_from_region(const struct intel_memory_region *mr,
static void
i915_ttm_placement_from_obj(const struct drm_i915_gem_object *obj,
struct ttm_place *requested,
struct ttm_place *busy,
struct ttm_place *places,
struct ttm_placement *placement)
{
unsigned int num_allowed = obj->mm.n_placements;
unsigned int flags = obj->flags;
unsigned int i;
placement->num_placement = 1;
places[0].flags |= TTM_PL_FLAG_DESIRED;
i915_ttm_place_from_region(num_allowed ? obj->mm.placements[0] :
obj->mm.region, requested, obj->bo_offset,
obj->mm.region, &places[0], obj->bo_offset,
obj->base.size, flags);
/* Cache this on object? */
placement->num_busy_placement = num_allowed;
for (i = 0; i < placement->num_busy_placement; ++i)
i915_ttm_place_from_region(obj->mm.placements[i], busy + i,
obj->bo_offset, obj->base.size, flags);
if (num_allowed == 0) {
*busy = *requested;
placement->num_busy_placement = 1;
for (i = 0; i < num_allowed; ++i) {
i915_ttm_place_from_region(obj->mm.placements[i],
&places[i + 1], obj->bo_offset,
obj->base.size, flags);
places[i + 1].flags |= TTM_PL_FLAG_FALLBACK;
}
placement->placement = requested;
placement->busy_placement = busy;
placement->num_placement = num_allowed + 1;
placement->placement = places;
}
static int i915_ttm_tt_shmem_populate(struct ttm_device *bdev,
@@ -789,7 +783,8 @@ static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
int ret;
/* First try only the requested placement. No eviction. */
real_num_busy = fetch_and_zero(&placement->num_busy_placement);
real_num_busy = placement->num_placement;
placement->num_placement = 1;
ret = ttm_bo_validate(bo, placement, &ctx);
if (ret) {
ret = i915_ttm_err_to_gem(ret);
@@ -805,7 +800,7 @@ static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
* If the initial attempt fails, allow all accepted placements,
* evicting if necessary.
*/
placement->num_busy_placement = real_num_busy;
placement->num_placement = real_num_busy;
ret = ttm_bo_validate(bo, placement, &ctx);
if (ret)
return i915_ttm_err_to_gem(ret);
@@ -839,7 +834,7 @@ static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
{
struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
struct ttm_place places[I915_TTM_MAX_PLACEMENTS + 1];
struct ttm_placement placement;
/* restricted by sg_alloc_table */
@@ -849,7 +844,7 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
GEM_BUG_ON(obj->mm.n_placements > I915_TTM_MAX_PLACEMENTS);
/* Move to the requested placement. */
i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
i915_ttm_placement_from_obj(obj, places, &placement);
return __i915_ttm_get_pages(obj, &placement);
}
@@ -879,9 +874,7 @@ static int __i915_ttm_migrate(struct drm_i915_gem_object *obj,
i915_ttm_place_from_region(mr, &requested, obj->bo_offset,
obj->base.size, flags);
placement.num_placement = 1;
placement.num_busy_placement = 1;
placement.placement = &requested;
placement.busy_placement = &requested;
ret = __i915_ttm_get_pages(obj, &placement);
if (ret)
+2 -11
View File
@@ -42,14 +42,13 @@ int dcss_blkctl_init(struct dcss_dev *dcss, unsigned long blkctl_base)
{
struct dcss_blkctl *blkctl;
blkctl = kzalloc(sizeof(*blkctl), GFP_KERNEL);
blkctl = devm_kzalloc(dcss->dev, sizeof(*blkctl), GFP_KERNEL);
if (!blkctl)
return -ENOMEM;
blkctl->base_reg = ioremap(blkctl_base, SZ_4K);
blkctl->base_reg = devm_ioremap(dcss->dev, blkctl_base, SZ_4K);
if (!blkctl->base_reg) {
dev_err(dcss->dev, "unable to remap BLK CTRL base\n");
kfree(blkctl);
return -ENOMEM;
}
@@ -60,11 +59,3 @@ int dcss_blkctl_init(struct dcss_dev *dcss, unsigned long blkctl_base)
return 0;
}
void dcss_blkctl_exit(struct dcss_blkctl *blkctl)
{
if (blkctl->base_reg)
iounmap(blkctl->base_reg);
kfree(blkctl);
}
+3 -11
View File
@@ -202,7 +202,7 @@ int dcss_ctxld_init(struct dcss_dev *dcss, unsigned long ctxld_base)
struct dcss_ctxld *ctxld;
int ret;
ctxld = kzalloc(sizeof(*ctxld), GFP_KERNEL);
ctxld = devm_kzalloc(dcss->dev, sizeof(*ctxld), GFP_KERNEL);
if (!ctxld)
return -ENOMEM;
@@ -217,7 +217,7 @@ int dcss_ctxld_init(struct dcss_dev *dcss, unsigned long ctxld_base)
goto err;
}
ctxld->ctxld_reg = ioremap(ctxld_base, SZ_4K);
ctxld->ctxld_reg = devm_ioremap(dcss->dev, ctxld_base, SZ_4K);
if (!ctxld->ctxld_reg) {
dev_err(dcss->dev, "ctxld: unable to remap ctxld base\n");
ret = -ENOMEM;
@@ -226,18 +226,14 @@ int dcss_ctxld_init(struct dcss_dev *dcss, unsigned long ctxld_base)
ret = dcss_ctxld_irq_config(ctxld, to_platform_device(dcss->dev));
if (ret)
goto err_irq;
goto err;
dcss_ctxld_hw_cfg(ctxld);
return 0;
err_irq:
iounmap(ctxld->ctxld_reg);
err:
dcss_ctxld_free_ctx(ctxld);
kfree(ctxld);
return ret;
}
@@ -246,11 +242,7 @@ void dcss_ctxld_exit(struct dcss_ctxld *ctxld)
{
free_irq(ctxld->irq, ctxld);
if (ctxld->ctxld_reg)
iounmap(ctxld->ctxld_reg);
dcss_ctxld_free_ctx(ctxld);
kfree(ctxld);
}
static int dcss_ctxld_enable_locked(struct dcss_ctxld *ctxld)
+9 -10
View File
@@ -109,8 +109,6 @@ dtg_err:
dcss_ctxld_exit(dcss->ctxld);
ctxld_err:
dcss_blkctl_exit(dcss->blkctl);
dcss_clocks_disable(dcss);
return ret;
@@ -124,7 +122,6 @@ static void dcss_submodules_stop(struct dcss_dev *dcss)
dcss_ss_exit(dcss->ss);
dcss_dtg_exit(dcss->dtg);
dcss_ctxld_exit(dcss->ctxld);
dcss_blkctl_exit(dcss->blkctl);
dcss_clocks_disable(dcss);
}
@@ -170,6 +167,7 @@ struct dcss_dev *dcss_dev_create(struct device *dev, bool hdmi_output)
struct resource *res;
struct dcss_dev *dcss;
const struct dcss_type_data *devtype;
resource_size_t res_len;
devtype = of_device_get_match_data(dev);
if (!devtype) {
@@ -183,7 +181,13 @@ struct dcss_dev *dcss_dev_create(struct device *dev, bool hdmi_output)
return ERR_PTR(-EINVAL);
}
dcss = kzalloc(sizeof(*dcss), GFP_KERNEL);
res_len = res->end - res->start;
if (!devm_request_mem_region(dev, res->start, res_len, "dcss")) {
dev_err(dev, "cannot request memory region\n");
return ERR_PTR(-EBUSY);
}
dcss = devm_kzalloc(dev, sizeof(*dcss), GFP_KERNEL);
if (!dcss)
return ERR_PTR(-ENOMEM);
@@ -194,7 +198,7 @@ struct dcss_dev *dcss_dev_create(struct device *dev, bool hdmi_output)
ret = dcss_clks_init(dcss);
if (ret) {
dev_err(dev, "clocks initialization failed\n");
goto err;
return ERR_PTR(ret);
}
dcss->of_port = of_graph_get_port_by_id(dev->of_node, 0);
@@ -226,9 +230,6 @@ struct dcss_dev *dcss_dev_create(struct device *dev, bool hdmi_output)
clks_err:
dcss_clks_release(dcss);
err:
kfree(dcss);
return ERR_PTR(ret);
}
@@ -246,8 +247,6 @@ void dcss_dev_destroy(struct dcss_dev *dcss)
dcss_submodules_stop(dcss);
dcss_clks_release(dcss);
kfree(dcss);
}
static int dcss_dev_suspend(struct device *dev)
-1
View File
@@ -104,7 +104,6 @@ extern const struct dev_pm_ops dcss_dev_pm_ops;
/* BLKCTL */
int dcss_blkctl_init(struct dcss_dev *dcss, unsigned long blkctl_base);
void dcss_blkctl_cfg(struct dcss_blkctl *blkctl);
void dcss_blkctl_exit(struct dcss_blkctl *blkctl);
/* CTXLD */
int dcss_ctxld_init(struct dcss_dev *dcss, unsigned long ctxld_base);
+3 -18
View File
@@ -135,7 +135,7 @@ static int dcss_dpr_ch_init_all(struct dcss_dpr *dpr, unsigned long dpr_base)
ch->base_ofs = dpr_base + i * 0x1000;
ch->base_reg = ioremap(ch->base_ofs, SZ_4K);
ch->base_reg = devm_ioremap(dpr->dev, ch->base_ofs, SZ_4K);
if (!ch->base_reg) {
dev_err(dpr->dev, "dpr: unable to remap ch %d base\n",
i);
@@ -155,7 +155,7 @@ int dcss_dpr_init(struct dcss_dev *dcss, unsigned long dpr_base)
{
struct dcss_dpr *dpr;
dpr = kzalloc(sizeof(*dpr), GFP_KERNEL);
dpr = devm_kzalloc(dcss->dev, sizeof(*dpr), GFP_KERNEL);
if (!dpr)
return -ENOMEM;
@@ -164,18 +164,8 @@ int dcss_dpr_init(struct dcss_dev *dcss, unsigned long dpr_base)
dpr->ctxld = dcss->ctxld;
dpr->ctx_id = CTX_SB_HP;
if (dcss_dpr_ch_init_all(dpr, dpr_base)) {
int i;
for (i = 0; i < 3; i++) {
if (dpr->ch[i].base_reg)
iounmap(dpr->ch[i].base_reg);
}
kfree(dpr);
if (dcss_dpr_ch_init_all(dpr, dpr_base))
return -ENOMEM;
}
return 0;
}
@@ -189,12 +179,7 @@ void dcss_dpr_exit(struct dcss_dpr *dpr)
struct dcss_dpr_ch *ch = &dpr->ch[ch_no];
dcss_writel(0, ch->base_reg + DCSS_DPR_SYSTEM_CTRL0);
if (ch->base_reg)
iounmap(ch->base_reg);
}
kfree(dpr);
}
static u32 dcss_dpr_x_pix_wide_adjust(struct dcss_dpr_ch *ch, u32 pix_wide,
+3 -9
View File
@@ -51,15 +51,13 @@ static int dcss_drv_platform_probe(struct platform_device *pdev)
of_node_put(remote);
mdrv = kzalloc(sizeof(*mdrv), GFP_KERNEL);
mdrv = devm_kzalloc(dev, sizeof(*mdrv), GFP_KERNEL);
if (!mdrv)
return -ENOMEM;
mdrv->dcss = dcss_dev_create(dev, hdmi_output);
if (IS_ERR(mdrv->dcss)) {
err = PTR_ERR(mdrv->dcss);
goto err;
}
if (IS_ERR(mdrv->dcss))
return PTR_ERR(mdrv->dcss);
dev_set_drvdata(dev, mdrv);
@@ -75,8 +73,6 @@ static int dcss_drv_platform_probe(struct platform_device *pdev)
dcss_shutoff:
dcss_dev_destroy(mdrv->dcss);
err:
kfree(mdrv);
return err;
}
@@ -86,8 +82,6 @@ static void dcss_drv_platform_remove(struct platform_device *pdev)
dcss_kms_detach(mdrv->kms);
dcss_dev_destroy(mdrv->dcss);
kfree(mdrv);
}
static void dcss_drv_platform_shutdown(struct platform_device *pdev)
+5 -21
View File
@@ -152,7 +152,7 @@ int dcss_dtg_init(struct dcss_dev *dcss, unsigned long dtg_base)
int ret = 0;
struct dcss_dtg *dtg;
dtg = kzalloc(sizeof(*dtg), GFP_KERNEL);
dtg = devm_kzalloc(dcss->dev, sizeof(*dtg), GFP_KERNEL);
if (!dtg)
return -ENOMEM;
@@ -160,11 +160,10 @@ int dcss_dtg_init(struct dcss_dev *dcss, unsigned long dtg_base)
dtg->dev = dcss->dev;
dtg->ctxld = dcss->ctxld;
dtg->base_reg = ioremap(dtg_base, SZ_4K);
dtg->base_reg = devm_ioremap(dtg->dev, dtg_base, SZ_4K);
if (!dtg->base_reg) {
dev_err(dcss->dev, "dtg: unable to remap dtg base\n");
ret = -ENOMEM;
goto err_ioremap;
dev_err(dtg->dev, "dtg: unable to remap dtg base\n");
return -ENOMEM;
}
dtg->base_ofs = dtg_base;
@@ -175,17 +174,7 @@ int dcss_dtg_init(struct dcss_dev *dcss, unsigned long dtg_base)
dtg->control_status |= OVL_DATA_MODE | BLENDER_VIDEO_ALPHA_SEL |
((dtg->alpha << DEFAULT_FG_ALPHA_POS) & DEFAULT_FG_ALPHA_MASK);
ret = dcss_dtg_irq_config(dtg, to_platform_device(dcss->dev));
if (ret)
goto err_irq;
return 0;
err_irq:
iounmap(dtg->base_reg);
err_ioremap:
kfree(dtg);
ret = dcss_dtg_irq_config(dtg, to_platform_device(dtg->dev));
return ret;
}
@@ -193,11 +182,6 @@ err_ioremap:
void dcss_dtg_exit(struct dcss_dtg *dtg)
{
free_irq(dtg->ctxld_kick_irq, dtg);
if (dtg->base_reg)
iounmap(dtg->base_reg);
kfree(dtg);
}
void dcss_dtg_sync_set(struct dcss_dtg *dtg, struct videomode *vm)
+3 -18
View File
@@ -302,7 +302,7 @@ static int dcss_scaler_ch_init_all(struct dcss_scaler *scl,
ch->base_ofs = scaler_base + i * 0x400;
ch->base_reg = ioremap(ch->base_ofs, SZ_4K);
ch->base_reg = devm_ioremap(scl->dev, ch->base_ofs, SZ_4K);
if (!ch->base_reg) {
dev_err(scl->dev, "scaler: unable to remap ch base\n");
return -ENOMEM;
@@ -318,7 +318,7 @@ int dcss_scaler_init(struct dcss_dev *dcss, unsigned long scaler_base)
{
struct dcss_scaler *scaler;
scaler = kzalloc(sizeof(*scaler), GFP_KERNEL);
scaler = devm_kzalloc(dcss->dev, sizeof(*scaler), GFP_KERNEL);
if (!scaler)
return -ENOMEM;
@@ -327,18 +327,8 @@ int dcss_scaler_init(struct dcss_dev *dcss, unsigned long scaler_base)
scaler->ctxld = dcss->ctxld;
scaler->ctx_id = CTX_SB_HP;
if (dcss_scaler_ch_init_all(scaler, scaler_base)) {
int i;
for (i = 0; i < 3; i++) {
if (scaler->ch[i].base_reg)
iounmap(scaler->ch[i].base_reg);
}
kfree(scaler);
if (dcss_scaler_ch_init_all(scaler, scaler_base))
return -ENOMEM;
}
return 0;
}
@@ -351,12 +341,7 @@ void dcss_scaler_exit(struct dcss_scaler *scl)
struct dcss_scaler_ch *ch = &scl->ch[ch_no];
dcss_writel(0, ch->base_reg + DCSS_SCALER_CTRL);
if (ch->base_reg)
iounmap(ch->base_reg);
}
kfree(scl);
}
void dcss_scaler_ch_enable(struct dcss_scaler *scl, int ch_num, bool en)
+3 -9
View File
@@ -83,7 +83,7 @@ int dcss_ss_init(struct dcss_dev *dcss, unsigned long ss_base)
{
struct dcss_ss *ss;
ss = kzalloc(sizeof(*ss), GFP_KERNEL);
ss = devm_kzalloc(dcss->dev, sizeof(*ss), GFP_KERNEL);
if (!ss)
return -ENOMEM;
@@ -91,10 +91,9 @@ int dcss_ss_init(struct dcss_dev *dcss, unsigned long ss_base)
ss->dev = dcss->dev;
ss->ctxld = dcss->ctxld;
ss->base_reg = ioremap(ss_base, SZ_4K);
ss->base_reg = devm_ioremap(ss->dev, ss_base, SZ_4K);
if (!ss->base_reg) {
dev_err(dcss->dev, "ss: unable to remap ss base\n");
kfree(ss);
dev_err(ss->dev, "ss: unable to remap ss base\n");
return -ENOMEM;
}
@@ -108,11 +107,6 @@ void dcss_ss_exit(struct dcss_ss *ss)
{
/* stop SS */
dcss_writel(0, ss->base_reg + DCSS_SS_SYS_CTRL);
if (ss->base_reg)
iounmap(ss->base_reg);
kfree(ss);
}
void dcss_ss_subsam_set(struct dcss_ss *ss)
+1 -1
View File
@@ -655,7 +655,7 @@ static int imx_ldb_probe(struct platform_device *pdev)
for (i = 0; i < 4; i++) {
char clkname[16];
sprintf(clkname, "di%d_sel", i);
snprintf(clkname, sizeof(clkname), "di%d_sel", i);
imx_ldb->clk_sel[i] = devm_clk_get(imx_ldb->dev, clkname);
if (IS_ERR(imx_ldb->clk_sel[i])) {
ret = PTR_ERR(imx_ldb->clk_sel[i]);
-1
View File
@@ -11,7 +11,6 @@ config DRM_INGENIC
select DRM_GEM_DMA_HELPER
select REGMAP
select REGMAP_MMIO
select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
help
Choose this option for DRM support for the Ingenic SoCs.
+14 -9
View File
@@ -75,29 +75,34 @@ int lima_heap_alloc(struct lima_bo *bo, struct lima_vm *vm)
} else {
bo->base.sgt = kmalloc(sizeof(*bo->base.sgt), GFP_KERNEL);
if (!bo->base.sgt) {
sg_free_table(&sgt);
return -ENOMEM;
ret = -ENOMEM;
goto err_out0;
}
}
ret = dma_map_sgtable(dev, &sgt, DMA_BIDIRECTIONAL, 0);
if (ret) {
sg_free_table(&sgt);
kfree(bo->base.sgt);
bo->base.sgt = NULL;
return ret;
}
if (ret)
goto err_out1;
*bo->base.sgt = sgt;
if (vm) {
ret = lima_vm_map_bo(vm, bo, old_size >> PAGE_SHIFT);
if (ret)
return ret;
goto err_out2;
}
bo->heap_size = new_size;
return 0;
err_out2:
dma_unmap_sgtable(dev, &sgt, DMA_BIDIRECTIONAL, 0);
err_out1:
kfree(bo->base.sgt);
bo->base.sgt = NULL;
err_out0:
sg_free_table(&sgt);
return ret;
}
int lima_gem_create_handle(struct drm_device *dev, struct drm_file *file,
+1 -1
View File
@@ -184,7 +184,7 @@ static int lsdc_get_dedicated_vram(struct lsdc_device *ldev,
drm_info(ddev, "Dedicated vram start: 0x%llx, size: %uMiB\n",
(u64)base, (u32)(size >> 20));
return 0;
return (size > SZ_1M) ? 0 : -ENODEV;
}
static struct lsdc_device *
-2
View File
@@ -54,7 +54,6 @@ static void lsdc_bo_set_placement(struct lsdc_bo *lbo, u32 domain)
pflags |= TTM_PL_FLAG_TOPDOWN;
lbo->placement.placement = lbo->placements;
lbo->placement.busy_placement = lbo->placements;
if (domain & LSDC_GEM_DOMAIN_VRAM) {
lbo->placements[c].mem_type = TTM_PL_VRAM;
@@ -77,7 +76,6 @@ static void lsdc_bo_set_placement(struct lsdc_bo *lbo, u32 domain)
}
lbo->placement.num_placement = c;
lbo->placement.num_busy_placement = c;
for (i = 0; i < c; ++i) {
lbo->placements[i].fpfn = 0;
-1
View File
@@ -11,7 +11,6 @@ config DRM_MCDE
select DRM_PANEL_BRIDGE
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
help
Choose this option for DRM support for the ST-Ericsson MCDE
Multi-Channel Display Engine.
+16 -4
View File
@@ -323,19 +323,31 @@ static void meson_encoder_hdmi_hpd_notify(struct drm_bridge *bridge,
enum drm_connector_status status)
{
struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge);
struct edid *edid;
if (!encoder_hdmi->cec_notifier)
return;
if (status == connector_status_connected) {
edid = drm_bridge_get_edid(encoder_hdmi->next_bridge, encoder_hdmi->connector);
if (!edid)
const struct drm_edid *drm_edid;
const struct edid *edid;
drm_edid = drm_bridge_edid_read(encoder_hdmi->next_bridge,
encoder_hdmi->connector);
if (!drm_edid)
return;
/*
* FIXME: The CEC physical address should be set using
* cec_notifier_set_phys_addr(encoder_hdmi->cec_notifier,
* connector->display_info.source_physical_address) from a path
* that has read the EDID and called
* drm_edid_connector_update().
*/
edid = drm_edid_raw(drm_edid);
cec_notifier_set_phys_addr_from_edid(encoder_hdmi->cec_notifier, edid);
kfree(edid);
drm_edid_free(drm_edid);
} else
cec_notifier_phys_addr_invalidate(encoder_hdmi->cec_notifier);
}
+1
View File
@@ -11,6 +11,7 @@
#include <linux/of_irq.h>
#include <linux/delay.h>
#include <drm/display/drm_dp_aux_bus.h>
#include <drm/drm_edid.h>
#include "msm_drv.h"
#include "msm_kms.h"
+23 -36
View File
@@ -404,27 +404,6 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align,
return 0;
}
static void
set_placement_list(struct ttm_place *pl, unsigned *n, uint32_t domain)
{
*n = 0;
if (domain & NOUVEAU_GEM_DOMAIN_VRAM) {
pl[*n].mem_type = TTM_PL_VRAM;
pl[*n].flags = 0;
(*n)++;
}
if (domain & NOUVEAU_GEM_DOMAIN_GART) {
pl[*n].mem_type = TTM_PL_TT;
pl[*n].flags = 0;
(*n)++;
}
if (domain & NOUVEAU_GEM_DOMAIN_CPU) {
pl[*n].mem_type = TTM_PL_SYSTEM;
pl[(*n)++].flags = 0;
}
}
static void
set_placement_range(struct nouveau_bo *nvbo, uint32_t domain)
{
@@ -452,10 +431,6 @@ set_placement_range(struct nouveau_bo *nvbo, uint32_t domain)
nvbo->placements[i].fpfn = fpfn;
nvbo->placements[i].lpfn = lpfn;
}
for (i = 0; i < nvbo->placement.num_busy_placement; ++i) {
nvbo->busy_placements[i].fpfn = fpfn;
nvbo->busy_placements[i].lpfn = lpfn;
}
}
}
@@ -463,15 +438,32 @@ void
nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t domain,
uint32_t busy)
{
struct ttm_placement *pl = &nvbo->placement;
unsigned int *n = &nvbo->placement.num_placement;
struct ttm_place *pl = nvbo->placements;
pl->placement = nvbo->placements;
set_placement_list(nvbo->placements, &pl->num_placement, domain);
domain |= busy;
pl->busy_placement = nvbo->busy_placements;
set_placement_list(nvbo->busy_placements, &pl->num_busy_placement,
domain | busy);
*n = 0;
if (domain & NOUVEAU_GEM_DOMAIN_VRAM) {
pl[*n].mem_type = TTM_PL_VRAM;
pl[*n].flags = busy & NOUVEAU_GEM_DOMAIN_VRAM ?
TTM_PL_FLAG_FALLBACK : 0;
(*n)++;
}
if (domain & NOUVEAU_GEM_DOMAIN_GART) {
pl[*n].mem_type = TTM_PL_TT;
pl[*n].flags = busy & NOUVEAU_GEM_DOMAIN_GART ?
TTM_PL_FLAG_FALLBACK : 0;
(*n)++;
}
if (domain & NOUVEAU_GEM_DOMAIN_CPU) {
pl[*n].mem_type = TTM_PL_SYSTEM;
pl[*n].flags = busy & NOUVEAU_GEM_DOMAIN_CPU ?
TTM_PL_FLAG_FALLBACK : 0;
(*n)++;
}
nvbo->placement.placement = nvbo->placements;
set_placement_range(nvbo, domain);
}
@@ -1314,11 +1306,6 @@ vm_fault_t nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
nvbo->placements[i].lpfn = mappable;
}
for (i = 0; i < nvbo->placement.num_busy_placement; ++i) {
nvbo->busy_placements[i].fpfn = 0;
nvbo->busy_placements[i].lpfn = mappable;
}
nouveau_bo_placement_set(nvbo, NOUVEAU_GEM_DOMAIN_VRAM, 0);
}
-1
View File
@@ -15,7 +15,6 @@ struct nouveau_bo {
struct ttm_placement placement;
u32 valid_domains;
struct ttm_place placements[3];
struct ttm_place busy_placements[3];
bool force_coherent;
struct ttm_bo_kmap_obj kmap;
struct list_head head;
+3 -7
View File
@@ -112,7 +112,7 @@ nouveau_svmm_bind(struct drm_device *dev, void *data,
{
struct nouveau_cli *cli = nouveau_cli(file_priv);
struct drm_nouveau_svm_bind *args = data;
unsigned target, cmd, priority;
unsigned target, cmd;
unsigned long addr, end;
struct mm_struct *mm;
@@ -136,9 +136,6 @@ nouveau_svmm_bind(struct drm_device *dev, void *data,
return -EINVAL;
}
priority = args->header >> NOUVEAU_SVM_BIND_PRIORITY_SHIFT;
priority &= NOUVEAU_SVM_BIND_PRIORITY_MASK;
/* FIXME support CPU target ie all target value < GPU_VRAM */
target = args->header >> NOUVEAU_SVM_BIND_TARGET_SHIFT;
target &= NOUVEAU_SVM_BIND_TARGET_MASK;
@@ -926,15 +923,14 @@ nouveau_pfns_map(struct nouveau_svmm *svmm, struct mm_struct *mm,
unsigned long addr, u64 *pfns, unsigned long npages)
{
struct nouveau_pfnmap_args *args = nouveau_pfns_to_args(pfns);
int ret;
args->p.addr = addr;
args->p.size = npages << PAGE_SHIFT;
mutex_lock(&svmm->mutex);
ret = nvif_object_ioctl(&svmm->vmm->vmm.object, args,
struct_size(args, p.phys, npages), NULL);
nvif_object_ioctl(&svmm->vmm->vmm.object, args,
struct_size(args, p.phys, npages), NULL);
mutex_unlock(&svmm->mutex);
}
@@ -218,7 +218,7 @@ nvkm_acr_lsfw_load_sig_image_desc_v2(struct nvkm_subdev *subdev,
const struct firmware *hsbl;
const struct nvfw_ls_hsbl_bin_hdr *hdr;
const struct nvfw_ls_hsbl_hdr *hshdr;
u32 loc, sig, cnt, *meta;
u32 sig, cnt, *meta;
ret = nvkm_firmware_load_name(subdev, path, "hs_bl_sig", ver, &hsbl);
if (ret)
@@ -227,7 +227,6 @@ nvkm_acr_lsfw_load_sig_image_desc_v2(struct nvkm_subdev *subdev,
hdr = nvfw_ls_hsbl_bin_hdr(subdev, hsbl->data);
hshdr = nvfw_ls_hsbl_hdr(subdev, hsbl->data + hdr->header_offset);
meta = (u32 *)(hsbl->data + hshdr->meta_data_offset);
loc = *(u32 *)(hsbl->data + hshdr->patch_loc);
sig = *(u32 *)(hsbl->data + hshdr->patch_sig);
cnt = *(u32 *)(hsbl->data + hshdr->num_sig);
+122 -101
View File
@@ -67,6 +67,17 @@ config DRM_PANEL_BOE_HIMAX8279D
24 bit RGB per pixel. It provides a MIPI DSI interface to
the host and has a built-in LED backlight.
config DRM_PANEL_BOE_TH101MB31UIG002_28A
tristate "Boe TH101MB31UIG002-28A panel"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
help
Say Y here if you want to enable support for Boe
TH101MB31UIG002-28A TFT-LCD modules. The panel has a 800x1280
resolution and uses 24 bit RGB per pixel. It provides a MIPI DSI
interface to the host and has a built-in LED backlight.
config DRM_PANEL_BOE_TV101WUM_NL6
tristate "BOE TV101WUM and AUO KD101N80 45NA 1200x1920 panel"
depends on OF
@@ -76,53 +87,6 @@ config DRM_PANEL_BOE_TV101WUM_NL6
Say Y here if you want to support for BOE TV101WUM and AUO KD101N80
45NA WUXGA PANEL DSI Video Mode panel
config DRM_PANEL_DSI_CM
tristate "Generic DSI command mode panels"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
help
DRM panel driver for DSI command mode panels with support for
embedded and external backlights.
config DRM_PANEL_LVDS
tristate "Generic LVDS panel driver"
depends on OF
depends on BACKLIGHT_CLASS_DEVICE
select VIDEOMODE_HELPERS
help
This driver supports LVDS panels that don't require device-specific
handling of power supplies or control signals. It implements automatic
backlight handling if the panel is attached to a backlight controller.
config DRM_PANEL_SIMPLE
tristate "support for simple panels (other than eDP ones)"
depends on OF
depends on BACKLIGHT_CLASS_DEVICE
depends on PM
select VIDEOMODE_HELPERS
help
DRM panel driver for dumb non-eDP panels that need at most a regulator
and a GPIO to be powered up. Optionally a backlight can be attached so
that it can be automatically turned off when the panel goes into a
low power state.
config DRM_PANEL_EDP
tristate "support for simple Embedded DisplayPort panels"
depends on OF
depends on BACKLIGHT_CLASS_DEVICE
depends on PM
select VIDEOMODE_HELPERS
select DRM_DISPLAY_DP_HELPER
select DRM_DISPLAY_HELPER
select DRM_DP_AUX_BUS
select DRM_KMS_HELPER
help
DRM panel driver for dumb eDP panels that need at most a regulator and
a GPIO to be powered up. Optionally a backlight can be attached so
that it can be automatically turned off when the panel goes into a
low power state.
config DRM_PANEL_EBBG_FT8719
tristate "EBBG FT8719 panel driver"
depends on OF
@@ -162,6 +126,25 @@ 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_DSI_CM
tristate "Generic DSI command mode panels"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
help
DRM panel driver for DSI command mode panels with support for
embedded and external backlights.
config DRM_PANEL_LVDS
tristate "Generic LVDS panel driver"
depends on OF
depends on BACKLIGHT_CLASS_DEVICE
select VIDEOMODE_HELPERS
help
This driver supports LVDS panels that don't require device-specific
handling of power supplies or control signals. It implements automatic
backlight handling if the panel is attached to a backlight controller.
config DRM_PANEL_HIMAX_HX8394
tristate "HIMAX HX8394 MIPI-DSI LCD panels"
depends on OF
@@ -251,17 +234,6 @@ config DRM_PANEL_JADARD_JD9365DA_H3
WXGA MIPI DSI panel. The panel support TFT dot matrix LCD with
800RGBx1280 dots at maximum.
config DRM_PANEL_JDI_LT070ME05000
tristate "JDI LT070ME05000 WUXGA DSI panel"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
help
Say Y here if you want to enable support for JDI DSI video mode
panel as found in Google Nexus 7 (2013) devices.
The panel has a 1200(RGB)×1920 (WUXGA) resolution and uses
24 bit per pixel.
config DRM_PANEL_JDI_LPM102A188A
tristate "JDI LPM102A188A DSI panel"
depends on OF && GPIOLIB
@@ -273,6 +245,17 @@ config DRM_PANEL_JDI_LPM102A188A
The panel has a 2560×1800 resolution. It provides a MIPI DSI interface
to the host.
config DRM_PANEL_JDI_LT070ME05000
tristate "JDI LT070ME05000 WUXGA DSI panel"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
help
Say Y here if you want to enable support for JDI DSI video mode
panel as found in Google Nexus 7 (2013) devices.
The panel has a 1200(RGB)×1920 (WUXGA) resolution and uses
24 bit per pixel.
config DRM_PANEL_JDI_R63452
tristate "JDI R63452 Full HD DSI panel"
depends on OF
@@ -326,12 +309,6 @@ config DRM_PANEL_LEADTEK_LTK500HD1829
24 bit RGB per pixel. It provides a MIPI DSI interface to
the host and has a built-in LED backlight.
config DRM_PANEL_SAMSUNG_LD9040
tristate "Samsung LD9040 RGB/SPI panel"
depends on OF && SPI
depends on BACKLIGHT_CLASS_DEVICE
select VIDEOMODE_HELPERS
config DRM_PANEL_LG_LB035Q02
tristate "LG LB035Q024573 RGB panel"
depends on GPIOLIB && OF && SPI
@@ -359,6 +336,17 @@ config DRM_PANEL_MAGNACHIP_D53E6EA8966
with the Magnachip D53E6EA8966 panel IC. This panel receives
video data via DSI but commands via 9-bit SPI using DBI.
config DRM_PANEL_MANTIX_MLAF057WE51
tristate "Mantix MLAF057WE51-X MIPI-DSI LCD panel"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
help
Say Y here if you want to enable support for the Mantix
MLAF057WE51-X MIPI DSI panel as e.g. used in the Librem 5. It
has a resolution of 720x1440 pixels, a built in backlight and touch
controller.
config DRM_PANEL_NEC_NL8048HL11
tristate "NEC NL8048HL11 RGB panel"
depends on GPIOLIB && OF && SPI
@@ -438,6 +426,16 @@ config DRM_PANEL_NOVATEK_NT36672A
around the Novatek NT36672A display controller, such as some
Tianma panels used in a few Xiaomi Poco F1 mobile phones.
config DRM_PANEL_NOVATEK_NT36672E
tristate "Novatek NT36672E DSI panel"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
help
Say Y here if you want to enable support for Novatek NT36672E DSI Video Mode
LCD panel module. The panel has a resolution of 1080x2408 and uses 24 bit
RGB per pixel.
config DRM_PANEL_NOVATEK_NT39016
tristate "Novatek NT39016 RGB/SPI panel"
depends on OF && SPI
@@ -447,17 +445,6 @@ config DRM_PANEL_NOVATEK_NT39016
Say Y here if you want to enable support for the panels built
around the Novatek NT39016 display controller.
config DRM_PANEL_MANTIX_MLAF057WE51
tristate "Mantix MLAF057WE51-X MIPI-DSI LCD panel"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
help
Say Y here if you want to enable support for the Mantix
MLAF057WE51-X MIPI DSI panel as e.g. used in the Librem 5. It
has a resolution of 720x1440 pixels, a built in backlight and touch
controller.
config DRM_PANEL_OLIMEX_LCD_OLINUXINO
tristate "Olimex LCD-OLinuXino panel"
depends on OF
@@ -554,6 +541,12 @@ config DRM_PANEL_RONBO_RB070D30
Say Y here if you want to enable support for Ronbo Electronics
RB070D30 1024x600 DSI panel.
config DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01
tristate "Samsung AMS452EF01 panel with S6E88A0 DSI video mode controller"
depends on OF
select DRM_MIPI_DSI
select VIDEOMODE_HELPERS
config DRM_PANEL_SAMSUNG_ATNA33XC20
tristate "Samsung ATNA33XC20 eDP panel"
depends on OF
@@ -577,6 +570,12 @@ config DRM_PANEL_SAMSUNG_DB7430
DB7430 DPI display controller used in such devices as the
LMS397KF04 480x800 DPI panel.
config DRM_PANEL_SAMSUNG_LD9040
tristate "Samsung LD9040 RGB/SPI panel"
depends on OF && SPI
depends on BACKLIGHT_CLASS_DEVICE
select VIDEOMODE_HELPERS
config DRM_PANEL_SAMSUNG_S6D16D0
tristate "Samsung S6D16D0 DSI video mode panel"
depends on OF
@@ -642,12 +641,6 @@ config DRM_PANEL_SAMSUNG_S6E63M0_DSI
Say Y here if you want to be able to access the Samsung
S6E63M0 panel using DSI.
config DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01
tristate "Samsung AMS452EF01 panel with S6E88A0 DSI video mode controller"
depends on OF
select DRM_MIPI_DSI
select VIDEOMODE_HELPERS
config DRM_PANEL_SAMSUNG_S6E8AA0
tristate "Samsung S6E8AA0 DSI video mode panel"
depends on OF
@@ -746,15 +739,6 @@ config DRM_PANEL_SITRONIX_ST7789V
Say Y here if you want to enable support for the Sitronix
ST7789V controller for 240x320 LCD panels
config DRM_PANEL_SYNAPTICS_R63353
tristate "Synaptics R63353-based 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
Synaptics R63353 controller.
config DRM_PANEL_SONY_ACX565AKM
tristate "Sony ACX565AKM panel"
depends on GPIOLIB && OF && SPI
@@ -794,6 +778,43 @@ config DRM_PANEL_STARTEK_KD070FHFID015
with a resolution of 1024 x 600 pixels. It provides a MIPI DSI interface to
the host, a built-in LED backlight and touch controller.
config DRM_PANEL_EDP
tristate "support for simple Embedded DisplayPort panels"
depends on OF
depends on BACKLIGHT_CLASS_DEVICE
depends on PM
select VIDEOMODE_HELPERS
select DRM_DISPLAY_DP_HELPER
select DRM_DISPLAY_HELPER
select DRM_DP_AUX_BUS
select DRM_KMS_HELPER
help
DRM panel driver for dumb eDP panels that need at most a regulator and
a GPIO to be powered up. Optionally a backlight can be attached so
that it can be automatically turned off when the panel goes into a
low power state.
config DRM_PANEL_SIMPLE
tristate "support for simple panels (other than eDP ones)"
depends on OF
depends on BACKLIGHT_CLASS_DEVICE
depends on PM
select VIDEOMODE_HELPERS
help
DRM panel driver for dumb non-eDP panels that need at most a regulator
and a GPIO to be powered up. Optionally a backlight can be attached so
that it can be automatically turned off when the panel goes into a
low power state.
config DRM_PANEL_SYNAPTICS_R63353
tristate "Synaptics R63353-based 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
Synaptics R63353 controller.
config DRM_PANEL_TDO_TL070WSH30
tristate "TDO TL070WSH30 DSI panel"
depends on OF
@@ -837,6 +858,17 @@ config DRM_PANEL_TRULY_NT35597_WQXGA
Say Y here if you want to enable support for Truly NT35597 WQXGA Dual DSI
Video Mode panel
config DRM_PANEL_VISIONOX_R66451
tristate "Visionox R66451"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
select DRM_DISPLAY_DP_HELPER
select DRM_DISPLAY_HELPER
help
Say Y here if you want to enable support for Visionox
R66451 1080x2340 AMOLED DSI panel.
config DRM_PANEL_VISIONOX_RM69299
tristate "Visionox RM69299"
depends on OF
@@ -854,17 +886,6 @@ config DRM_PANEL_VISIONOX_VTDR6130
Say Y here if you want to enable support for Visionox
VTDR6130 1080x2400 AMOLED DSI panel.
config DRM_PANEL_VISIONOX_R66451
tristate "Visionox R66451"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
select DRM_DISPLAY_DP_HELPER
select DRM_DISPLAY_HELPER
help
Say Y here if you want to enable support for Visionox
R66451 1080x2340 AMOLED DSI panel.
config DRM_PANEL_WIDECHIPS_WS2401
tristate "Widechips WS2401 DPI panel driver"
depends on SPI && GPIOLIB
+2
View File
@@ -5,6 +5,7 @@ obj-$(CONFIG_DRM_PANEL_ASUS_Z00T_TM5P5_NT35596) += panel-asus-z00t-tm5p5-n35596.
obj-$(CONFIG_DRM_PANEL_AUO_A030JTN01) += panel-auo-a030jtn01.o
obj-$(CONFIG_DRM_PANEL_BOE_BF060Y8M_AJ0) += panel-boe-bf060y8m-aj0.o
obj-$(CONFIG_DRM_PANEL_BOE_HIMAX8279D) += panel-boe-himax8279d.o
obj-$(CONFIG_DRM_PANEL_BOE_TH101MB31UIG002_28A) += panel-boe-th101mb31ig002-28a.o
obj-$(CONFIG_DRM_PANEL_BOE_TV101WUM_NL6) += panel-boe-tv101wum-nl6.o
obj-$(CONFIG_DRM_PANEL_DSI_CM) += panel-dsi-cm.o
obj-$(CONFIG_DRM_PANEL_LVDS) += panel-lvds.o
@@ -41,6 +42,7 @@ obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35560) += panel-novatek-nt35560.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35950) += panel-novatek-nt35950.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36523) += panel-novatek-nt36523.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36672A) += panel-novatek-nt36672a.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36672E) += panel-novatek-nt36672e.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT39016) += panel-novatek-nt39016.o
obj-$(CONFIG_DRM_PANEL_MANTIX_MLAF057WE51) += panel-mantix-mlaf057we51.o
obj-$(CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO) += panel-olimex-lcd-olinuxino.o
+6 -12
View File
@@ -854,26 +854,20 @@ static int panel_add(struct panel_info *pinfo)
pinfo->pp18_gpio = devm_gpiod_get(dev, "pp18", GPIOD_OUT_HIGH);
if (IS_ERR(pinfo->pp18_gpio)) {
ret = PTR_ERR(pinfo->pp18_gpio);
if (ret != -EPROBE_DEFER)
dev_err(dev, "failed to get pp18 gpio: %d\n", ret);
return ret;
return dev_err_probe(dev, PTR_ERR(pinfo->pp18_gpio),
"failed to get pp18 gpio\n");
}
pinfo->pp33_gpio = devm_gpiod_get(dev, "pp33", GPIOD_OUT_HIGH);
if (IS_ERR(pinfo->pp33_gpio)) {
ret = PTR_ERR(pinfo->pp33_gpio);
if (ret != -EPROBE_DEFER)
dev_err(dev, "failed to get pp33 gpio: %d\n", ret);
return ret;
return dev_err_probe(dev, PTR_ERR(pinfo->pp33_gpio),
"failed to get pp33 gpio\n");
}
pinfo->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
if (IS_ERR(pinfo->enable_gpio)) {
ret = PTR_ERR(pinfo->enable_gpio);
if (ret != -EPROBE_DEFER)
dev_err(dev, "failed to get enable gpio: %d\n", ret);
return ret;
return dev_err_probe(dev, PTR_ERR(pinfo->enable_gpio),
"failed to get enable gpio\n");
}
drm_panel_init(&pinfo->base, dev, &panel_funcs,
@@ -0,0 +1,322 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2023 Alexander Warnecke <awarnecke002@hotmail.com>
* Copyright (c) 2023 Manuel Traut <manut@mecka.net>
* Copyright (c) 2023 Dang Huynh <danct12@riseup.net>
*/
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/regulator/consumer.h>
#include <drm/drm_connector.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_modes.h>
#include <drm/drm_panel.h>
struct boe_th101mb31ig002 {
struct drm_panel panel;
struct mipi_dsi_device *dsi;
struct regulator *power;
struct gpio_desc *enable;
struct gpio_desc *reset;
enum drm_panel_orientation orientation;
};
static void boe_th101mb31ig002_reset(struct boe_th101mb31ig002 *ctx)
{
gpiod_direction_output(ctx->reset, 0);
usleep_range(10, 100);
gpiod_direction_output(ctx->reset, 1);
usleep_range(10, 100);
gpiod_direction_output(ctx->reset, 0);
usleep_range(5000, 6000);
}
static int boe_th101mb31ig002_enable(struct drm_panel *panel)
{
struct boe_th101mb31ig002 *ctx = container_of(panel,
struct boe_th101mb31ig002,
panel);
struct mipi_dsi_device *dsi = ctx->dsi;
struct device *dev = &dsi->dev;
int ret;
mipi_dsi_dcs_write_seq(dsi, 0xE0, 0xAB, 0xBA);
mipi_dsi_dcs_write_seq(dsi, 0xE1, 0xBA, 0xAB);
mipi_dsi_dcs_write_seq(dsi, 0xB1, 0x10, 0x01, 0x47, 0xFF);
mipi_dsi_dcs_write_seq(dsi, 0xB2, 0x0C, 0x14, 0x04, 0x50, 0x50, 0x14);
mipi_dsi_dcs_write_seq(dsi, 0xB3, 0x56, 0x53, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0xB4, 0x33, 0x30, 0x04);
mipi_dsi_dcs_write_seq(dsi, 0xB6, 0xB0, 0x00, 0x00, 0x10, 0x00, 0x10,
0x00);
mipi_dsi_dcs_write_seq(dsi, 0xB8, 0x05, 0x12, 0x29, 0x49, 0x48, 0x00,
0x00);
mipi_dsi_dcs_write_seq(dsi, 0xB9, 0x7C, 0x65, 0x55, 0x49, 0x46, 0x36,
0x3B, 0x24, 0x3D, 0x3C, 0x3D, 0x5C, 0x4C,
0x55, 0x47, 0x46, 0x39, 0x26, 0x06, 0x7C,
0x65, 0x55, 0x49, 0x46, 0x36, 0x3B, 0x24,
0x3D, 0x3C, 0x3D, 0x5C, 0x4C, 0x55, 0x47,
0x46, 0x39, 0x26, 0x06);
mipi_dsi_dcs_write_seq(dsi, 0x00, 0xFF, 0x87, 0x12, 0x34, 0x44, 0x44,
0x44, 0x44, 0x98, 0x04, 0x98, 0x04, 0x0F,
0x00, 0x00, 0xC1);
mipi_dsi_dcs_write_seq(dsi, 0xC1, 0x54, 0x94, 0x02, 0x85, 0x9F, 0x00,
0x7F, 0x00, 0x54, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0xC2, 0x17, 0x09, 0x08, 0x89, 0x08, 0x11,
0x22, 0x20, 0x44, 0xFF, 0x18, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0xC3, 0x86, 0x46, 0x05, 0x05, 0x1C, 0x1C,
0x1D, 0x1D, 0x02, 0x1F, 0x1F, 0x1E, 0x1E,
0x0F, 0x0F, 0x0D, 0x0D, 0x13, 0x13, 0x11,
0x11, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0xC4, 0x07, 0x07, 0x04, 0x04, 0x1C, 0x1C,
0x1D, 0x1D, 0x02, 0x1F, 0x1F, 0x1E, 0x1E,
0x0E, 0x0E, 0x0C, 0x0C, 0x12, 0x12, 0x10,
0x10, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0xC6, 0x2A, 0x2A);
mipi_dsi_dcs_write_seq(dsi, 0xC8, 0x21, 0x00, 0x31, 0x42, 0x34, 0x16);
mipi_dsi_dcs_write_seq(dsi, 0xCA, 0xCB, 0x43);
mipi_dsi_dcs_write_seq(dsi, 0xCD, 0x0E, 0x4B, 0x4B, 0x20, 0x19, 0x6B,
0x06, 0xB3);
mipi_dsi_dcs_write_seq(dsi, 0xD2, 0xE3, 0x2B, 0x38, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0xD4, 0x00, 0x01, 0x00, 0x0E, 0x04, 0x44,
0x08, 0x10, 0x00, 0x00, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0xE6, 0x80, 0x01, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF);
mipi_dsi_dcs_write_seq(dsi, 0xF0, 0x12, 0x03, 0x20, 0x00, 0xFF);
mipi_dsi_dcs_write_seq(dsi, 0xF3, 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 panel on: %d\n", ret);
return ret;
}
return 0;
}
static int boe_th101mb31ig002_disable(struct drm_panel *panel)
{
struct boe_th101mb31ig002 *ctx = container_of(panel,
struct boe_th101mb31ig002,
panel);
struct mipi_dsi_device *dsi = ctx->dsi;
struct device *dev = &dsi->dev;
int ret;
ret = mipi_dsi_dcs_set_display_off(dsi);
if (ret < 0)
dev_err(dev, "Failed to set panel off: %d\n", ret);
msleep(120);
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
if (ret < 0)
dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
return 0;
}
static int boe_th101mb31ig002_unprepare(struct drm_panel *panel)
{
struct boe_th101mb31ig002 *ctx = container_of(panel,
struct boe_th101mb31ig002,
panel);
gpiod_set_value_cansleep(ctx->reset, 1);
gpiod_set_value_cansleep(ctx->enable, 0);
regulator_disable(ctx->power);
return 0;
}
static int boe_th101mb31ig002_prepare(struct drm_panel *panel)
{
struct boe_th101mb31ig002 *ctx = container_of(panel,
struct boe_th101mb31ig002,
panel);
struct device *dev = &ctx->dsi->dev;
int ret;
ret = regulator_enable(ctx->power);
if (ret) {
dev_err(dev, "Failed to enable power supply: %d\n", ret);
return ret;
}
gpiod_set_value_cansleep(ctx->enable, 1);
msleep(50);
boe_th101mb31ig002_reset(ctx);
boe_th101mb31ig002_enable(panel);
return 0;
}
static const struct drm_display_mode boe_th101mb31ig002_default_mode = {
.clock = 73500,
.hdisplay = 800,
.hsync_start = 800 + 64,
.hsync_end = 800 + 64 + 16,
.htotal = 800 + 64 + 16 + 64,
.vdisplay = 1280,
.vsync_start = 1280 + 2,
.vsync_end = 1280 + 2 + 4,
.vtotal = 1280 + 2 + 4 + 12,
.width_mm = 135,
.height_mm = 216,
.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
};
static int boe_th101mb31ig002_get_modes(struct drm_panel *panel,
struct drm_connector *connector)
{
struct boe_th101mb31ig002 *ctx = container_of(panel,
struct boe_th101mb31ig002,
panel);
struct drm_display_mode *mode;
mode = drm_mode_duplicate(connector->dev,
&boe_th101mb31ig002_default_mode);
if (!mode) {
dev_err(panel->dev, "Failed to add mode %ux%u@%u\n",
boe_th101mb31ig002_default_mode.hdisplay,
boe_th101mb31ig002_default_mode.vdisplay,
drm_mode_vrefresh(&boe_th101mb31ig002_default_mode));
return -ENOMEM;
}
drm_mode_set_name(mode);
connector->display_info.bpc = 8;
connector->display_info.width_mm = mode->width_mm;
connector->display_info.height_mm = mode->height_mm;
/*
* TODO: Remove once all drm drivers call
* drm_connector_set_orientation_from_panel()
*/
drm_connector_set_panel_orientation(connector, ctx->orientation);
drm_mode_probed_add(connector, mode);
return 1;
}
static enum drm_panel_orientation
boe_th101mb31ig002_get_orientation(struct drm_panel *panel)
{
struct boe_th101mb31ig002 *ctx = container_of(panel,
struct boe_th101mb31ig002,
panel);
return ctx->orientation;
}
static const struct drm_panel_funcs boe_th101mb31ig002_funcs = {
.prepare = boe_th101mb31ig002_prepare,
.unprepare = boe_th101mb31ig002_unprepare,
.disable = boe_th101mb31ig002_disable,
.get_modes = boe_th101mb31ig002_get_modes,
.get_orientation = boe_th101mb31ig002_get_orientation,
};
static int boe_th101mb31ig002_dsi_probe(struct mipi_dsi_device *dsi)
{
struct boe_th101mb31ig002 *ctx;
int ret;
ctx = devm_kzalloc(&dsi->dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
mipi_dsi_set_drvdata(dsi, ctx);
ctx->dsi = dsi;
dsi->lanes = 4;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO_BURST |
MIPI_DSI_MODE_NO_EOT_PACKET |
MIPI_DSI_MODE_LPM;
ctx->power = devm_regulator_get(&dsi->dev, "power");
if (IS_ERR(ctx->power))
return dev_err_probe(&dsi->dev, PTR_ERR(ctx->power),
"Failed to get power regulator\n");
ctx->enable = devm_gpiod_get(&dsi->dev, "enable", GPIOD_OUT_LOW);
if (IS_ERR(ctx->enable))
return dev_err_probe(&dsi->dev, PTR_ERR(ctx->enable),
"Failed to get enable GPIO\n");
ctx->reset = devm_gpiod_get(&dsi->dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(ctx->reset))
return dev_err_probe(&dsi->dev, PTR_ERR(ctx->reset),
"Failed to get reset GPIO\n");
ret = of_drm_get_panel_orientation(dsi->dev.of_node,
&ctx->orientation);
if (ret)
return dev_err_probe(&dsi->dev, ret,
"Failed to get orientation\n");
drm_panel_init(&ctx->panel, &dsi->dev, &boe_th101mb31ig002_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(&dsi->dev, ret,
"Failed to attach panel to DSI host\n");
drm_panel_remove(&ctx->panel);
return ret;
}
return 0;
}
static void boe_th101mb31ig002_dsi_remove(struct mipi_dsi_device *dsi)
{
struct boe_th101mb31ig002 *ctx = mipi_dsi_get_drvdata(dsi);
mipi_dsi_detach(dsi);
drm_panel_remove(&ctx->panel);
}
static const struct of_device_id boe_th101mb31ig002_of_match[] = {
{ .compatible = "boe,th101mb31ig002-28a", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, boe_th101mb31ig002_of_match);
static struct mipi_dsi_driver boe_th101mb31ig002_driver = {
.driver = {
.name = "boe-th101mb31ig002-28a",
.of_match_table = boe_th101mb31ig002_of_match,
},
.probe = boe_th101mb31ig002_dsi_probe,
.remove = boe_th101mb31ig002_dsi_remove,
};
module_mipi_dsi_driver(boe_th101mb31ig002_driver);
MODULE_AUTHOR("Alexander Warnecke <awarnecke002@hotmail.com>");
MODULE_DESCRIPTION("BOE TH101MB31IG002-28A MIPI-DSI LCD panel");
MODULE_LICENSE("GPL");
@@ -933,8 +933,7 @@ static int j606f_boe_init_sequence(struct panel_info *pinfo)
static const struct drm_display_mode elish_boe_modes[] = {
{
/* There is only one 120 Hz timing, but it doesn't work perfectly, 104 Hz preferred */
.clock = (1600 + 60 + 8 + 60) * (2560 + 26 + 4 + 168) * 104 / 1000,
.clock = (1600 + 60 + 8 + 60) * (2560 + 26 + 4 + 168) * 120 / 1000,
.hdisplay = 1600,
.hsync_start = 1600 + 60,
.hsync_end = 1600 + 60 + 8,
@@ -948,8 +947,7 @@ static const struct drm_display_mode elish_boe_modes[] = {
static const struct drm_display_mode elish_csot_modes[] = {
{
/* There is only one 120 Hz timing, but it doesn't work perfectly, 104 Hz preferred */
.clock = (1600 + 200 + 40 + 52) * (2560 + 26 + 4 + 168) * 104 / 1000,
.clock = (1600 + 200 + 40 + 52) * (2560 + 26 + 4 + 168) * 120 / 1000,
.hdisplay = 1600,
.hsync_start = 1600 + 200,
.hsync_end = 1600 + 200 + 40,
@@ -1270,6 +1268,8 @@ static int nt36523_probe(struct mipi_dsi_device *dsi)
return ret;
}
pinfo->panel.prepare_prev_first = true;
if (pinfo->desc->has_dcs_backlight) {
pinfo->panel.backlight = nt36523_create_backlight(dsi);
if (IS_ERR(pinfo->panel.backlight))
@@ -0,0 +1,643 @@
// SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regulator/consumer.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_modes.h>
#include <drm/drm_panel.h>
#include <video/mipi_display.h>
static const char * const regulator_names[] = {
"vddi",
"avdd",
"avee",
};
static const unsigned long regulator_enable_loads[] = {
62000,
100000,
100000,
};
static const unsigned long regulator_disable_loads[] = {
80,
100,
100,
};
struct panel_desc {
const struct drm_display_mode *display_mode;
u32 width_mm;
u32 height_mm;
unsigned long mode_flags;
enum mipi_dsi_pixel_format format;
unsigned int lanes;
const char *panel_name;
int (*init_sequence)(struct mipi_dsi_device *dsi);
};
struct nt36672e_panel {
struct drm_panel panel;
struct mipi_dsi_device *dsi;
struct gpio_desc *reset_gpio;
struct regulator_bulk_data supplies[3];
const struct panel_desc *desc;
};
static inline struct nt36672e_panel *to_nt36672e_panel(struct drm_panel *panel)
{
return container_of(panel, struct nt36672e_panel, panel);
}
static int nt36672e_1080x2408_60hz_init(struct mipi_dsi_device *dsi)
{
mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10);
mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0xc0, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0xc1, 0x89, 0x28, 0x00, 0x08, 0x00, 0xaa, 0x02,
0x0e, 0x00, 0x2b, 0x00, 0x07, 0x0d, 0xb7, 0x0c, 0xb7);
mipi_dsi_dcs_write_seq(dsi, 0xc2, 0x1b, 0xa0);
mipi_dsi_dcs_write_seq(dsi, 0xff, 0x20);
mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
mipi_dsi_dcs_write_seq(dsi, 0x01, 0x66);
mipi_dsi_dcs_write_seq(dsi, 0x06, 0x40);
mipi_dsi_dcs_write_seq(dsi, 0x07, 0x38);
mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x83);
mipi_dsi_dcs_write_seq(dsi, 0x69, 0x91);
mipi_dsi_dcs_write_seq(dsi, 0x95, 0xd1);
mipi_dsi_dcs_write_seq(dsi, 0x96, 0xd1);
mipi_dsi_dcs_write_seq(dsi, 0xf2, 0x64);
mipi_dsi_dcs_write_seq(dsi, 0xf3, 0x54);
mipi_dsi_dcs_write_seq(dsi, 0xf4, 0x64);
mipi_dsi_dcs_write_seq(dsi, 0xf5, 0x54);
mipi_dsi_dcs_write_seq(dsi, 0xf6, 0x64);
mipi_dsi_dcs_write_seq(dsi, 0xf7, 0x54);
mipi_dsi_dcs_write_seq(dsi, 0xf8, 0x64);
mipi_dsi_dcs_write_seq(dsi, 0xf9, 0x54);
mipi_dsi_dcs_write_seq(dsi, 0xff, 0x24);
mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
mipi_dsi_dcs_write_seq(dsi, 0x01, 0x0f);
mipi_dsi_dcs_write_seq(dsi, 0x03, 0x0c);
mipi_dsi_dcs_write_seq(dsi, 0x05, 0x1d);
mipi_dsi_dcs_write_seq(dsi, 0x08, 0x2f);
mipi_dsi_dcs_write_seq(dsi, 0x09, 0x2e);
mipi_dsi_dcs_write_seq(dsi, 0x0a, 0x2d);
mipi_dsi_dcs_write_seq(dsi, 0x0b, 0x2c);
mipi_dsi_dcs_write_seq(dsi, 0x11, 0x17);
mipi_dsi_dcs_write_seq(dsi, 0x12, 0x13);
mipi_dsi_dcs_write_seq(dsi, 0x13, 0x15);
mipi_dsi_dcs_write_seq(dsi, 0x15, 0x14);
mipi_dsi_dcs_write_seq(dsi, 0x16, 0x16);
mipi_dsi_dcs_write_seq(dsi, 0x17, 0x18);
mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x01);
mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x1d);
mipi_dsi_dcs_write_seq(dsi, 0x20, 0x2f);
mipi_dsi_dcs_write_seq(dsi, 0x21, 0x2e);
mipi_dsi_dcs_write_seq(dsi, 0x22, 0x2d);
mipi_dsi_dcs_write_seq(dsi, 0x23, 0x2c);
mipi_dsi_dcs_write_seq(dsi, 0x29, 0x17);
mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x13);
mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x15);
mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x14);
mipi_dsi_dcs_write_seq(dsi, 0x30, 0x16);
mipi_dsi_dcs_write_seq(dsi, 0x31, 0x18);
mipi_dsi_dcs_write_seq(dsi, 0x32, 0x04);
mipi_dsi_dcs_write_seq(dsi, 0x34, 0x10);
mipi_dsi_dcs_write_seq(dsi, 0x35, 0x1f);
mipi_dsi_dcs_write_seq(dsi, 0x36, 0x1f);
mipi_dsi_dcs_write_seq(dsi, 0x4d, 0x14);
mipi_dsi_dcs_write_seq(dsi, 0x4e, 0x36);
mipi_dsi_dcs_write_seq(dsi, 0x4f, 0x36);
mipi_dsi_dcs_write_seq(dsi, 0x53, 0x36);
mipi_dsi_dcs_write_seq(dsi, 0x71, 0x30);
mipi_dsi_dcs_write_seq(dsi, 0x79, 0x11);
mipi_dsi_dcs_write_seq(dsi, 0x7a, 0x82);
mipi_dsi_dcs_write_seq(dsi, 0x7b, 0x8f);
mipi_dsi_dcs_write_seq(dsi, 0x7d, 0x04);
mipi_dsi_dcs_write_seq(dsi, 0x80, 0x04);
mipi_dsi_dcs_write_seq(dsi, 0x81, 0x04);
mipi_dsi_dcs_write_seq(dsi, 0x82, 0x13);
mipi_dsi_dcs_write_seq(dsi, 0x84, 0x31);
mipi_dsi_dcs_write_seq(dsi, 0x85, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0x86, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0x87, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0x90, 0x13);
mipi_dsi_dcs_write_seq(dsi, 0x92, 0x31);
mipi_dsi_dcs_write_seq(dsi, 0x93, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0x94, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0x95, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0x9c, 0xf4);
mipi_dsi_dcs_write_seq(dsi, 0x9d, 0x01);
mipi_dsi_dcs_write_seq(dsi, 0xa0, 0x0f);
mipi_dsi_dcs_write_seq(dsi, 0xa2, 0x0f);
mipi_dsi_dcs_write_seq(dsi, 0xa3, 0x02);
mipi_dsi_dcs_write_seq(dsi, 0xa4, 0x04);
mipi_dsi_dcs_write_seq(dsi, 0xa5, 0x04);
mipi_dsi_dcs_write_seq(dsi, 0xc6, 0xc0);
mipi_dsi_dcs_write_seq(dsi, 0xc9, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0xd9, 0x80);
mipi_dsi_dcs_write_seq(dsi, 0xe9, 0x02);
mipi_dsi_dcs_write_seq(dsi, 0xff, 0x25);
mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
mipi_dsi_dcs_write_seq(dsi, 0x18, 0x22);
mipi_dsi_dcs_write_seq(dsi, 0x19, 0xe4);
mipi_dsi_dcs_write_seq(dsi, 0x21, 0x40);
mipi_dsi_dcs_write_seq(dsi, 0x66, 0xd8);
mipi_dsi_dcs_write_seq(dsi, 0x68, 0x50);
mipi_dsi_dcs_write_seq(dsi, 0x69, 0x10);
mipi_dsi_dcs_write_seq(dsi, 0x6b, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0x6d, 0x0d);
mipi_dsi_dcs_write_seq(dsi, 0x6e, 0x48);
mipi_dsi_dcs_write_seq(dsi, 0x72, 0x41);
mipi_dsi_dcs_write_seq(dsi, 0x73, 0x4a);
mipi_dsi_dcs_write_seq(dsi, 0x74, 0xd0);
mipi_dsi_dcs_write_seq(dsi, 0x77, 0x62);
mipi_dsi_dcs_write_seq(dsi, 0x79, 0x7e);
mipi_dsi_dcs_write_seq(dsi, 0x7d, 0x03);
mipi_dsi_dcs_write_seq(dsi, 0x7e, 0x15);
mipi_dsi_dcs_write_seq(dsi, 0x7f, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0x84, 0x4d);
mipi_dsi_dcs_write_seq(dsi, 0xcf, 0x80);
mipi_dsi_dcs_write_seq(dsi, 0xd6, 0x80);
mipi_dsi_dcs_write_seq(dsi, 0xd7, 0x80);
mipi_dsi_dcs_write_seq(dsi, 0xef, 0x20);
mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x84);
mipi_dsi_dcs_write_seq(dsi, 0xff, 0x26);
mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
mipi_dsi_dcs_write_seq(dsi, 0x81, 0x0f);
mipi_dsi_dcs_write_seq(dsi, 0x83, 0x01);
mipi_dsi_dcs_write_seq(dsi, 0x84, 0x03);
mipi_dsi_dcs_write_seq(dsi, 0x85, 0x01);
mipi_dsi_dcs_write_seq(dsi, 0x86, 0x03);
mipi_dsi_dcs_write_seq(dsi, 0x87, 0x01);
mipi_dsi_dcs_write_seq(dsi, 0x88, 0x05);
mipi_dsi_dcs_write_seq(dsi, 0x8a, 0x1a);
mipi_dsi_dcs_write_seq(dsi, 0x8b, 0x11);
mipi_dsi_dcs_write_seq(dsi, 0x8c, 0x24);
mipi_dsi_dcs_write_seq(dsi, 0x8e, 0x42);
mipi_dsi_dcs_write_seq(dsi, 0x8f, 0x11);
mipi_dsi_dcs_write_seq(dsi, 0x90, 0x11);
mipi_dsi_dcs_write_seq(dsi, 0x91, 0x11);
mipi_dsi_dcs_write_seq(dsi, 0x9a, 0x80);
mipi_dsi_dcs_write_seq(dsi, 0x9b, 0x04);
mipi_dsi_dcs_write_seq(dsi, 0x9c, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0x9d, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0x9e, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0xff, 0x27);
mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
mipi_dsi_dcs_write_seq(dsi, 0x01, 0x68);
mipi_dsi_dcs_write_seq(dsi, 0x20, 0x81);
mipi_dsi_dcs_write_seq(dsi, 0x21, 0x6a);
mipi_dsi_dcs_write_seq(dsi, 0x25, 0x81);
mipi_dsi_dcs_write_seq(dsi, 0x26, 0x94);
mipi_dsi_dcs_write_seq(dsi, 0x6e, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0x6f, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0x70, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0x71, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0x72, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0x75, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0x76, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0x77, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0x7d, 0x09);
mipi_dsi_dcs_write_seq(dsi, 0x7e, 0x67);
mipi_dsi_dcs_write_seq(dsi, 0x80, 0x23);
mipi_dsi_dcs_write_seq(dsi, 0x82, 0x09);
mipi_dsi_dcs_write_seq(dsi, 0x83, 0x67);
mipi_dsi_dcs_write_seq(dsi, 0x88, 0x01);
mipi_dsi_dcs_write_seq(dsi, 0x89, 0x10);
mipi_dsi_dcs_write_seq(dsi, 0xa5, 0x10);
mipi_dsi_dcs_write_seq(dsi, 0xa6, 0x23);
mipi_dsi_dcs_write_seq(dsi, 0xa7, 0x01);
mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x40);
mipi_dsi_dcs_write_seq(dsi, 0xe5, 0x02);
mipi_dsi_dcs_write_seq(dsi, 0xe6, 0xd3);
mipi_dsi_dcs_write_seq(dsi, 0xeb, 0x03);
mipi_dsi_dcs_write_seq(dsi, 0xec, 0x28);
mipi_dsi_dcs_write_seq(dsi, 0xff, 0x2a);
mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
mipi_dsi_dcs_write_seq(dsi, 0x00, 0x91);
mipi_dsi_dcs_write_seq(dsi, 0x03, 0x20);
mipi_dsi_dcs_write_seq(dsi, 0x07, 0x50);
mipi_dsi_dcs_write_seq(dsi, 0x0a, 0x70);
mipi_dsi_dcs_write_seq(dsi, 0x0c, 0x04);
mipi_dsi_dcs_write_seq(dsi, 0x0d, 0x40);
mipi_dsi_dcs_write_seq(dsi, 0x0f, 0x01);
mipi_dsi_dcs_write_seq(dsi, 0x11, 0xe0);
mipi_dsi_dcs_write_seq(dsi, 0x15, 0x0f);
mipi_dsi_dcs_write_seq(dsi, 0x16, 0xa4);
mipi_dsi_dcs_write_seq(dsi, 0x19, 0x0f);
mipi_dsi_dcs_write_seq(dsi, 0x1a, 0x78);
mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x23);
mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x36);
mipi_dsi_dcs_write_seq(dsi, 0x1e, 0x3e);
mipi_dsi_dcs_write_seq(dsi, 0x1f, 0x3e);
mipi_dsi_dcs_write_seq(dsi, 0x20, 0x3e);
mipi_dsi_dcs_write_seq(dsi, 0x28, 0xfd);
mipi_dsi_dcs_write_seq(dsi, 0x29, 0x12);
mipi_dsi_dcs_write_seq(dsi, 0x2a, 0xe1);
mipi_dsi_dcs_write_seq(dsi, 0x2d, 0x0a);
mipi_dsi_dcs_write_seq(dsi, 0x30, 0x49);
mipi_dsi_dcs_write_seq(dsi, 0x33, 0x96);
mipi_dsi_dcs_write_seq(dsi, 0x34, 0xff);
mipi_dsi_dcs_write_seq(dsi, 0x35, 0x40);
mipi_dsi_dcs_write_seq(dsi, 0x36, 0xde);
mipi_dsi_dcs_write_seq(dsi, 0x37, 0xf9);
mipi_dsi_dcs_write_seq(dsi, 0x38, 0x45);
mipi_dsi_dcs_write_seq(dsi, 0x39, 0xd9);
mipi_dsi_dcs_write_seq(dsi, 0x3a, 0x49);
mipi_dsi_dcs_write_seq(dsi, 0x4a, 0xf0);
mipi_dsi_dcs_write_seq(dsi, 0x7a, 0x09);
mipi_dsi_dcs_write_seq(dsi, 0x7b, 0x40);
mipi_dsi_dcs_write_seq(dsi, 0x7f, 0xf0);
mipi_dsi_dcs_write_seq(dsi, 0x83, 0x0f);
mipi_dsi_dcs_write_seq(dsi, 0x84, 0xa4);
mipi_dsi_dcs_write_seq(dsi, 0x87, 0x0f);
mipi_dsi_dcs_write_seq(dsi, 0x88, 0x78);
mipi_dsi_dcs_write_seq(dsi, 0x89, 0x23);
mipi_dsi_dcs_write_seq(dsi, 0x8b, 0x36);
mipi_dsi_dcs_write_seq(dsi, 0x8c, 0x7d);
mipi_dsi_dcs_write_seq(dsi, 0x8d, 0x7d);
mipi_dsi_dcs_write_seq(dsi, 0x8e, 0x7d);
mipi_dsi_dcs_write_seq(dsi, 0xff, 0x20);
mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00, 0x00, 0x00, 0x17, 0x00, 0x49, 0x00,
0x6a, 0x00, 0x89, 0x00, 0x9f, 0x00, 0xb6, 0x00, 0xc8);
mipi_dsi_dcs_write_seq(dsi, 0xb1, 0x00, 0xd9, 0x01, 0x10, 0x01, 0x3a, 0x01,
0x7a, 0x01, 0xa9, 0x01, 0xf2, 0x02, 0x2d, 0x02, 0x2e);
mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x02, 0x64, 0x02, 0xa3, 0x02, 0xca, 0x03,
0x00, 0x03, 0x1e, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
0x71, 0x00, 0x90, 0x00, 0xa7, 0x00, 0xbf, 0x00, 0xd1);
mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x00, 0xe2, 0x01, 0x1a, 0x01, 0x43, 0x01,
0x83, 0x01, 0xb2, 0x01, 0xfa, 0x02, 0x34, 0x02, 0x36);
mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x02, 0x6b, 0x02, 0xa8, 0x02, 0xd0, 0x03,
0x03, 0x03, 0x21, 0x03, 0x4d, 0x03, 0x5b, 0x03, 0x6b);
mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x03, 0x7e, 0x03, 0x94, 0x03, 0xac, 0x03,
0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
0x72, 0x00, 0x92, 0x00, 0xa8, 0x00, 0xbf, 0x00, 0xd1);
mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0xe2, 0x01, 0x18, 0x01, 0x42, 0x01,
0x81, 0x01, 0xaf, 0x01, 0xf5, 0x02, 0x2f, 0x02, 0x31);
mipi_dsi_dcs_write_seq(dsi, 0xba, 0x02, 0x68, 0x02, 0xa6, 0x02, 0xcd, 0x03,
0x01, 0x03, 0x1f, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0xff, 0x21);
mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00, 0x00, 0x00, 0x17, 0x00, 0x49, 0x00,
0x6a, 0x00, 0x89, 0x00, 0x9f, 0x00, 0xb6, 0x00, 0xc8);
mipi_dsi_dcs_write_seq(dsi, 0xb1, 0x00, 0xd9, 0x01, 0x10, 0x01, 0x3a, 0x01,
0x7a, 0x01, 0xa9, 0x01, 0xf2, 0x02, 0x2d, 0x02, 0x2e);
mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x02, 0x64, 0x02, 0xa3, 0x02, 0xca, 0x03,
0x00, 0x03, 0x1e, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
0x71, 0x00, 0x90, 0x00, 0xa7, 0x00, 0xbf, 0x00, 0xd1);
mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x00, 0xe2, 0x01, 0x1a, 0x01, 0x43, 0x01,
0x83, 0x01, 0xb2, 0x01, 0xfa, 0x02, 0x34, 0x02, 0x36);
mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x02, 0x6b, 0x02, 0xa8, 0x02, 0xd0, 0x03,
0x03, 0x03, 0x21, 0x03, 0x4d, 0x03, 0x5b, 0x03, 0x6b);
mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x03, 0x7e, 0x03, 0x94, 0x03, 0xac, 0x03,
0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
0x72, 0x00, 0x92, 0x00, 0xa8, 0x00, 0xbf, 0x00, 0xd1);
mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0xe2, 0x01, 0x18, 0x01, 0x42, 0x01,
0x81, 0x01, 0xaf, 0x01, 0xf5, 0x02, 0x2f, 0x02, 0x31);
mipi_dsi_dcs_write_seq(dsi, 0xba, 0x02, 0x68, 0x02, 0xa6, 0x02, 0xcd, 0x03,
0x01, 0x03, 0x1f, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0xff, 0x2c);
mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
mipi_dsi_dcs_write_seq(dsi, 0x61, 0x1f);
mipi_dsi_dcs_write_seq(dsi, 0x62, 0x1f);
mipi_dsi_dcs_write_seq(dsi, 0x7e, 0x03);
mipi_dsi_dcs_write_seq(dsi, 0x6a, 0x14);
mipi_dsi_dcs_write_seq(dsi, 0x6b, 0x36);
mipi_dsi_dcs_write_seq(dsi, 0x6c, 0x36);
mipi_dsi_dcs_write_seq(dsi, 0x6d, 0x36);
mipi_dsi_dcs_write_seq(dsi, 0x53, 0x04);
mipi_dsi_dcs_write_seq(dsi, 0x54, 0x04);
mipi_dsi_dcs_write_seq(dsi, 0x55, 0x04);
mipi_dsi_dcs_write_seq(dsi, 0x56, 0x0f);
mipi_dsi_dcs_write_seq(dsi, 0x58, 0x0f);
mipi_dsi_dcs_write_seq(dsi, 0x59, 0x0f);
mipi_dsi_dcs_write_seq(dsi, 0xff, 0xf0);
mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
mipi_dsi_dcs_write_seq(dsi, 0x5a, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10);
mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
mipi_dsi_dcs_write_seq(dsi, 0x51, 0xff);
mipi_dsi_dcs_write_seq(dsi, 0x53, 0x24);
mipi_dsi_dcs_write_seq(dsi, 0x55, 0x01);
return 0;
}
static int nt36672e_power_on(struct nt36672e_panel *ctx)
{
struct mipi_dsi_device *dsi = ctx->dsi;
int ret, i;
for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++) {
ret = regulator_set_load(ctx->supplies[i].consumer,
regulator_enable_loads[i]);
if (ret) {
dev_err(&dsi->dev, "regulator set load failed for supply %s: %d\n",
ctx->supplies[i].supply, ret);
return ret;
}
}
ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
if (ret < 0) {
dev_err(&dsi->dev, "regulator bulk enable failed: %d\n", ret);
return ret;
}
/*
* Reset sequence of nt36672e panel requires the panel to be out of reset
* for 10ms, followed by being held in reset for 10ms and then out again.
*/
gpiod_set_value(ctx->reset_gpio, 1);
usleep_range(10000, 20000);
gpiod_set_value(ctx->reset_gpio, 0);
usleep_range(10000, 20000);
gpiod_set_value(ctx->reset_gpio, 1);
usleep_range(10000, 20000);
return 0;
}
static int nt36672e_power_off(struct nt36672e_panel *ctx)
{
struct mipi_dsi_device *dsi = ctx->dsi;
int ret = 0;
int i;
gpiod_set_value(ctx->reset_gpio, 0);
for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++) {
ret = regulator_set_load(ctx->supplies[i].consumer,
regulator_disable_loads[i]);
if (ret) {
dev_err(&dsi->dev, "regulator set load failed for supply %s: %d\n",
ctx->supplies[i].supply, ret);
return ret;
}
}
ret = regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
if (ret)
dev_err(&dsi->dev, "regulator bulk disable failed: %d\n", ret);
return ret;
}
static int nt36672e_on(struct nt36672e_panel *ctx)
{
struct mipi_dsi_device *dsi = ctx->dsi;
const struct panel_desc *desc = ctx->desc;
int ret = 0;
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
if (desc->init_sequence) {
ret = desc->init_sequence(dsi);
if (ret < 0) {
dev_err(&dsi->dev, "panel init sequence failed: %d\n", ret);
return ret;
}
}
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
if (ret < 0) {
dev_err(&dsi->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(&dsi->dev, "Failed to set display on: %d\n", ret);
return ret;
}
msleep(100);
return 0;
}
static int nt36672e_off(struct nt36672e_panel *ctx)
{
struct mipi_dsi_device *dsi = ctx->dsi;
int ret = 0;
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
ret = mipi_dsi_dcs_set_display_off(dsi);
if (ret < 0) {
dev_err(&dsi->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(&dsi->dev, "Failed to enter sleep mode: %d\n", ret);
return ret;
}
msleep(60);
return 0;
}
static int nt36672e_panel_prepare(struct drm_panel *panel)
{
struct nt36672e_panel *ctx = to_nt36672e_panel(panel);
struct mipi_dsi_device *dsi = ctx->dsi;
int ret = 0;
ret = nt36672e_power_on(ctx);
if (ret < 0)
return ret;
ret = nt36672e_on(ctx);
if (ret < 0) {
dev_err(&dsi->dev, "Failed to initialize panel: %d\n", ret);
if (nt36672e_power_off(ctx))
dev_err(&dsi->dev, "power off failed\n");
return ret;
}
return 0;
}
static int nt36672e_panel_unprepare(struct drm_panel *panel)
{
struct nt36672e_panel *ctx = to_nt36672e_panel(panel);
struct mipi_dsi_device *dsi = ctx->dsi;
int ret = 0;
ret = nt36672e_off(ctx);
if (ret < 0)
dev_err(&dsi->dev, "Failed to un-initialize panel: %d\n", ret);
ret = nt36672e_power_off(ctx);
if (ret < 0)
dev_err(&dsi->dev, "power off failed: %d\n", ret);
return 0;
}
static const struct drm_display_mode nt36672e_1080x2408_60hz = {
.name = "1080x2408",
.clock = 181690,
.hdisplay = 1080,
.hsync_start = 1080 + 76,
.hsync_end = 1080 + 76 + 12,
.htotal = 1080 + 76 + 12 + 56,
.vdisplay = 2408,
.vsync_start = 2408 + 46,
.vsync_end = 2408 + 46 + 10,
.vtotal = 2408 + 46 + 10 + 10,
.flags = 0,
};
static const struct panel_desc nt36672e_panel_desc = {
.display_mode = &nt36672e_1080x2408_60hz,
.width_mm = 74,
.height_mm = 131,
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS,
.format = MIPI_DSI_FMT_RGB888,
.lanes = 4,
.panel_name = "nt36672e fhd plus panel",
.init_sequence = nt36672e_1080x2408_60hz_init,
};
static int nt36672e_panel_get_modes(struct drm_panel *panel, struct drm_connector *connector)
{
struct nt36672e_panel *ctx = to_nt36672e_panel(panel);
struct drm_display_mode *mode;
mode = drm_mode_duplicate(connector->dev, ctx->desc->display_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 = ctx->desc->width_mm;
connector->display_info.height_mm = ctx->desc->height_mm;
drm_mode_probed_add(connector, mode);
return 1;
}
static const struct drm_panel_funcs nt36672e_drm_funcs = {
.prepare = nt36672e_panel_prepare,
.unprepare = nt36672e_panel_unprepare,
.get_modes = nt36672e_panel_get_modes,
};
static int nt36672e_panel_probe(struct mipi_dsi_device *dsi)
{
struct device *dev = &dsi->dev;
struct nt36672e_panel *ctx;
int i, ret = 0;
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
ctx->desc = of_device_get_match_data(dev);
if (!ctx->desc) {
dev_err(dev, "missing device configuration\n");
return -ENODEV;
}
for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++)
ctx->supplies[i].supply = regulator_names[i];
ret = devm_regulator_bulk_get(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 = ctx->desc->lanes;
dsi->format = ctx->desc->format;
dsi->mode_flags = ctx->desc->mode_flags;
drm_panel_init(&ctx->panel, dev, &nt36672e_drm_funcs, DRM_MODE_CONNECTOR_DSI);
ret = drm_panel_of_backlight(&ctx->panel);
if (ret)
return dev_err_probe(dev, ret, "Failed to get backlight\n");
ctx->panel.prepare_prev_first = true;
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);
goto err_dsi_attach;
}
return 0;
err_dsi_attach:
drm_panel_remove(&ctx->panel);
return ret;
}
static void nt36672e_panel_remove(struct mipi_dsi_device *dsi)
{
struct nt36672e_panel *ctx = mipi_dsi_get_drvdata(dsi);
mipi_dsi_detach(ctx->dsi);
mipi_dsi_device_unregister(ctx->dsi);
drm_panel_remove(&ctx->panel);
}
static const struct of_device_id nt36672e_of_match[] = {
{
.compatible = "novatek,nt36672e",
.data = &nt36672e_panel_desc,
},
{ }
};
MODULE_DEVICE_TABLE(of, nt36672e_of_match);
static struct mipi_dsi_driver nt36672e_panel_driver = {
.driver = {
.name = "panel-novatek-nt36672e",
.of_match_table = nt36672e_of_match,
},
.probe = nt36672e_panel_probe,
.remove = nt36672e_panel_remove,
};
module_mipi_dsi_driver(nt36672e_panel_driver);
MODULE_AUTHOR("Ritesh Kumar <quic_riteshk@quicinc.com>");
MODULE_DESCRIPTION("Novatek NT36672E DSI Panel Driver");
MODULE_LICENSE("GPL");
+46 -15
View File
@@ -1980,6 +1980,33 @@ static const struct panel_desc edt_etml0700y5dha = {
.connector_type = DRM_MODE_CONNECTOR_LVDS,
};
static const struct display_timing edt_etml1010g3dra_timing = {
.pixelclock = { 66300000, 72400000, 78900000 },
.hactive = { 1280, 1280, 1280 },
.hfront_porch = { 12, 72, 132 },
.hback_porch = { 86, 86, 86 },
.hsync_len = { 2, 2, 2 },
.vactive = { 800, 800, 800 },
.vfront_porch = { 1, 15, 49 },
.vback_porch = { 21, 21, 21 },
.vsync_len = { 2, 2, 2 },
.flags = DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_HSYNC_LOW |
DISPLAY_FLAGS_DE_HIGH,
};
static const struct panel_desc edt_etml1010g3dra = {
.timings = &edt_etml1010g3dra_timing,
.num_timings = 1,
.bpc = 8,
.size = {
.width = 216,
.height = 135,
},
.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
.bus_flags = DRM_BUS_FLAG_DE_HIGH,
.connector_type = DRM_MODE_CONNECTOR_LVDS,
};
static const struct drm_display_mode edt_etmv570g2dhu_mode = {
.clock = 25175,
.hdisplay = 640,
@@ -2754,21 +2781,21 @@ static const struct panel_desc lemaker_bl035_rgb_002 = {
.bus_flags = DRM_BUS_FLAG_DE_LOW,
};
static const struct drm_display_mode lg_lb070wv8_mode = {
.clock = 33246,
.hdisplay = 800,
.hsync_start = 800 + 88,
.hsync_end = 800 + 88 + 80,
.htotal = 800 + 88 + 80 + 88,
.vdisplay = 480,
.vsync_start = 480 + 10,
.vsync_end = 480 + 10 + 25,
.vtotal = 480 + 10 + 25 + 10,
static const struct display_timing lg_lb070wv8_timing = {
.pixelclock = { 31950000, 33260000, 34600000 },
.hactive = { 800, 800, 800 },
.hfront_porch = { 88, 88, 88 },
.hback_porch = { 88, 88, 88 },
.hsync_len = { 80, 80, 80 },
.vactive = { 480, 480, 480 },
.vfront_porch = { 10, 10, 10 },
.vback_porch = { 10, 10, 10 },
.vsync_len = { 25, 25, 25 },
};
static const struct panel_desc lg_lb070wv8 = {
.modes = &lg_lb070wv8_mode,
.num_modes = 1,
.timings = &lg_lb070wv8_timing,
.num_timings = 1,
.bpc = 8,
.size = {
.width = 151,
@@ -3516,14 +3543,15 @@ static const struct display_timing rocktech_rk043fn48h_timing = {
.pixelclock = { 6000000, 9000000, 12000000 },
.hactive = { 480, 480, 480 },
.hback_porch = { 8, 43, 43 },
.hfront_porch = { 2, 8, 8 },
.hfront_porch = { 2, 8, 10 },
.hsync_len = { 1, 1, 1 },
.vactive = { 272, 272, 272 },
.vback_porch = { 2, 12, 12 },
.vback_porch = { 2, 12, 26 },
.vfront_porch = { 1, 4, 4 },
.vsync_len = { 1, 10, 10 },
.flags = DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_HSYNC_LOW |
DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE,
DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE |
DISPLAY_FLAGS_SYNC_POSEDGE,
};
static const struct panel_desc rocktech_rk043fn48h = {
@@ -4423,6 +4451,9 @@ static const struct of_device_id platform_of_match[] = {
}, {
.compatible = "edt,etml0700y5dha",
.data = &edt_etml0700y5dha,
}, {
.compatible = "edt,etml1010g3dra",
.data = &edt_etml1010g3dra,
}, {
.compatible = "edt,etmv570g2dhu",
.data = &edt_etmv570g2dhu,
@@ -322,6 +322,7 @@ static int visionox_r66451_probe(struct mipi_dsi_device *dsi)
dsi->lanes = 4;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS;
ctx->panel.prepare_prev_first = true;
drm_panel_init(&ctx->panel, dev, &visionox_r66451_funcs, DRM_MODE_CONNECTOR_DSI);
ctx->panel.backlight = visionox_r66451_create_backlight(dsi);
@@ -287,6 +287,7 @@ static int visionox_vtdr6130_probe(struct mipi_dsi_device *dsi)
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_NO_EOT_PACKET |
MIPI_DSI_CLOCK_NON_CONTINUOUS;
ctx->panel.prepare_prev_first = true;
drm_panel_init(&ctx->panel, dev, &visionox_vtdr6130_panel_funcs,
DRM_MODE_CONNECTOR_DSI);
-1
View File
@@ -9,7 +9,6 @@ config DRM_PL111
select DRM_GEM_DMA_HELPER
select DRM_BRIDGE
select DRM_PANEL_BRIDGE
select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
help
Choose this option for DRM support for the PL111 CLCD controller.
If M is selected the module will be called pl111_drm.
-2
View File
@@ -66,7 +66,6 @@ void qxl_ttm_placement_from_domain(struct qxl_bo *qbo, u32 domain)
pflag |= TTM_PL_FLAG_TOPDOWN;
qbo->placement.placement = qbo->placements;
qbo->placement.busy_placement = qbo->placements;
if (domain == QXL_GEM_DOMAIN_VRAM) {
qbo->placements[c].mem_type = TTM_PL_VRAM;
qbo->placements[c++].flags = pflag;
@@ -86,7 +85,6 @@ void qxl_ttm_placement_from_domain(struct qxl_bo *qbo, u32 domain)
qbo->placements[c++].flags = 0;
}
qbo->placement.num_placement = c;
qbo->placement.num_busy_placement = c;
for (i = 0; i < c; ++i) {
qbo->placements[i].fpfn = 0;
qbo->placements[i].lpfn = 0;
-2
View File
@@ -60,9 +60,7 @@ static void qxl_evict_flags(struct ttm_buffer_object *bo,
if (!qxl_ttm_bo_is_qxl_bo(bo)) {
placement->placement = &placements;
placement->busy_placement = &placements;
placement->num_placement = 1;
placement->num_busy_placement = 1;
return;
}
qbo = to_qxl_bo(bo);
-2
View File
@@ -78,7 +78,6 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
u32 c = 0, i;
rbo->placement.placement = rbo->placements;
rbo->placement.busy_placement = rbo->placements;
if (domain & RADEON_GEM_DOMAIN_VRAM) {
/* Try placing BOs which don't need CPU access outside of the
* CPU accessible part of VRAM
@@ -114,7 +113,6 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
}
rbo->placement.num_placement = c;
rbo->placement.num_busy_placement = c;
for (i = 0; i < c; ++i) {
if ((rbo->flags & RADEON_GEM_CPU_ACCESS) &&
+1 -7
View File
@@ -92,9 +92,7 @@ static void radeon_evict_flags(struct ttm_buffer_object *bo,
if (!radeon_ttm_bo_is_radeon_bo(bo)) {
placement->placement = &placements;
placement->busy_placement = &placements;
placement->num_placement = 1;
placement->num_busy_placement = 1;
return;
}
rbo = container_of(bo, struct radeon_bo, tbo);
@@ -114,15 +112,11 @@ static void radeon_evict_flags(struct ttm_buffer_object *bo,
*/
radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM |
RADEON_GEM_DOMAIN_GTT);
rbo->placement.num_busy_placement = 0;
for (i = 0; i < rbo->placement.num_placement; i++) {
if (rbo->placements[i].mem_type == TTM_PL_VRAM) {
if (rbo->placements[i].fpfn < fpfn)
rbo->placements[i].fpfn = fpfn;
} else {
rbo->placement.busy_placement =
&rbo->placements[i];
rbo->placement.num_busy_placement = 1;
rbo->placements[0].flags |= TTM_PL_FLAG_DESIRED;
}
}
} else
-1
View File
@@ -324,7 +324,6 @@ void radeon_uvd_force_into_uvd_segment(struct radeon_bo *rbo,
rbo->placements[1].fpfn += (256 * 1024 * 1024) >> PAGE_SHIFT;
rbo->placements[1].lpfn += (256 * 1024 * 1024) >> PAGE_SHIFT;
rbo->placement.num_placement++;
rbo->placement.num_busy_placement++;
}
void radeon_uvd_free_handles(struct radeon_device *rdev, struct drm_file *filp)
+1
View File
@@ -15,6 +15,7 @@
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_edid.h>
#include <drm/drm_of.h>
+1
View File
@@ -24,6 +24,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_debugfs.h>
#include <drm/drm_edid.h>
#include <drm/drm_eld.h>
#include <drm/drm_file.h>
#include <drm/drm_fourcc.h>
+62 -17
View File
@@ -12,6 +12,7 @@
#define TEST_TIMEOUT_MS 100
struct managed_test_priv {
struct drm_device *drm;
bool action_done;
wait_queue_head_t action_wq;
};
@@ -24,13 +25,58 @@ static void drm_action(struct drm_device *drm, void *ptr)
wake_up_interruptible(&priv->action_wq);
}
/*
* The test verifies that the release action is called when
* drmm_release_action is called.
*/
static void drm_test_managed_release_action(struct kunit *test)
{
struct managed_test_priv *priv = test->priv;
int ret;
ret = drmm_add_action_or_reset(priv->drm, drm_action, priv);
KUNIT_EXPECT_EQ(test, ret, 0);
ret = drm_dev_register(priv->drm, 0);
KUNIT_ASSERT_EQ(test, ret, 0);
drmm_release_action(priv->drm, drm_action, priv);
ret = wait_event_interruptible_timeout(priv->action_wq, priv->action_done,
msecs_to_jiffies(TEST_TIMEOUT_MS));
KUNIT_EXPECT_GT(test, ret, 0);
drm_dev_unregister(priv->drm);
drm_kunit_helper_free_device(test, priv->drm->dev);
}
/*
* The test verifies that the release action is called automatically when the
* device is released.
*/
static void drm_test_managed_run_action(struct kunit *test)
{
struct managed_test_priv *priv;
struct drm_device *drm;
struct device *dev;
struct managed_test_priv *priv = test->priv;
int ret;
ret = drmm_add_action_or_reset(priv->drm, drm_action, priv);
KUNIT_EXPECT_EQ(test, ret, 0);
ret = drm_dev_register(priv->drm, 0);
KUNIT_ASSERT_EQ(test, ret, 0);
drm_dev_unregister(priv->drm);
drm_kunit_helper_free_device(test, priv->drm->dev);
ret = wait_event_interruptible_timeout(priv->action_wq, priv->action_done,
msecs_to_jiffies(TEST_TIMEOUT_MS));
KUNIT_EXPECT_GT(test, ret, 0);
}
static int drm_managed_test_init(struct kunit *test)
{
struct managed_test_priv *priv;
struct device *dev;
priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
init_waitqueue_head(&priv->action_wq);
@@ -38,30 +84,29 @@ static void drm_test_managed_run_action(struct kunit *test)
dev = drm_kunit_helper_alloc_device(test);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
drm = __drm_kunit_helper_alloc_drm_device(test, dev, sizeof(*drm), 0, DRIVER_MODESET);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, drm);
/*
* DRM device can't be embedded in priv, since priv->action_done needs
* to remain allocated beyond both parent device and drm_device
* lifetime.
*/
priv->drm = __drm_kunit_helper_alloc_drm_device(test, dev, sizeof(*priv->drm), 0,
DRIVER_MODESET);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm);
ret = drmm_add_action_or_reset(drm, drm_action, priv);
KUNIT_EXPECT_EQ(test, ret, 0);
test->priv = priv;
ret = drm_dev_register(drm, 0);
KUNIT_ASSERT_EQ(test, ret, 0);
drm_dev_unregister(drm);
drm_kunit_helper_free_device(test, dev);
ret = wait_event_interruptible_timeout(priv->action_wq, priv->action_done,
msecs_to_jiffies(TEST_TIMEOUT_MS));
KUNIT_EXPECT_GT(test, ret, 0);
return 0;
}
static struct kunit_case drm_managed_tests[] = {
KUNIT_CASE(drm_test_managed_release_action),
KUNIT_CASE(drm_test_managed_run_action),
{}
};
static struct kunit_suite drm_managed_test_suite = {
.name = "drm-test-managed",
.name = "drm_managed",
.init = drm_managed_test_init,
.test_cases = drm_managed_tests
};
+18 -10
View File
@@ -410,8 +410,8 @@ static int ttm_bo_bounce_temp_buffer(struct ttm_buffer_object *bo,
struct ttm_resource *hop_mem;
int ret;
hop_placement.num_placement = hop_placement.num_busy_placement = 1;
hop_placement.placement = hop_placement.busy_placement = hop;
hop_placement.num_placement = 1;
hop_placement.placement = hop;
/* find space in the bounce domain */
ret = ttm_bo_mem_space(bo, &hop_placement, &hop_mem, ctx);
@@ -440,10 +440,9 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo,
dma_resv_assert_held(bo->base.resv);
placement.num_placement = 0;
placement.num_busy_placement = 0;
bdev->funcs->evict_flags(bo, &placement);
if (!placement.num_placement && !placement.num_busy_placement) {
if (!placement.num_placement) {
ret = ttm_bo_wait_ctx(bo, ctx);
if (ret)
return ret;
@@ -770,7 +769,7 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo,
* This function may sleep while waiting for space to become available.
* Returns:
* -EBUSY: No space available (only if no_wait == 1).
* -ENOMEM: Could not allocate memory for the buffer object, either due to
* -ENOSPC: Could not allocate space for the buffer object, either due to
* fragmentation or concurrent allocators.
* -ERESTARTSYS: An interruptible sleep was interrupted by a signal.
*/
@@ -791,6 +790,9 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
const struct ttm_place *place = &placement->placement[i];
struct ttm_resource_manager *man;
if (place->flags & TTM_PL_FLAG_FALLBACK)
continue;
man = ttm_manager_type(bdev, place->mem_type);
if (!man || !ttm_resource_manager_used(man))
continue;
@@ -813,10 +815,13 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
return 0;
}
for (i = 0; i < placement->num_busy_placement; ++i) {
const struct ttm_place *place = &placement->busy_placement[i];
for (i = 0; i < placement->num_placement; ++i) {
const struct ttm_place *place = &placement->placement[i];
struct ttm_resource_manager *man;
if (place->flags & TTM_PL_FLAG_DESIRED)
continue;
man = ttm_manager_type(bdev, place->mem_type);
if (!man || !ttm_resource_manager_used(man))
continue;
@@ -830,7 +835,7 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
goto error;
}
ret = -ENOMEM;
ret = -ENOSPC;
if (!type_found) {
pr_err(TTM_PFX "No compatible memory type found\n");
ret = -EINVAL;
@@ -904,11 +909,11 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
/*
* Remove the backing store if no placement is given.
*/
if (!placement->num_placement && !placement->num_busy_placement)
if (!placement->num_placement)
return ttm_bo_pipeline_gutting(bo);
/* Check whether we need to move buffer. */
if (bo->resource && ttm_resource_compat(bo->resource, placement))
if (bo->resource && ttm_resource_compatible(bo->resource, placement))
return 0;
/* Moving of pinned BOs is forbidden */
@@ -916,6 +921,9 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
return -EINVAL;
ret = ttm_bo_move_buffer(bo, placement, ctx);
/* For backward compatibility with userspace */
if (ret == -ENOSPC)
return -ENOMEM;
if (ret)
return ret;
+11 -2
View File
@@ -294,7 +294,13 @@ pgprot_t ttm_io_prot(struct ttm_buffer_object *bo, struct ttm_resource *res,
enum ttm_caching caching;
man = ttm_manager_type(bo->bdev, res->mem_type);
caching = man->use_tt ? bo->ttm->caching : res->bus.caching;
if (man->use_tt) {
caching = bo->ttm->caching;
if (bo->ttm->page_flags & TTM_TT_FLAG_DECRYPTED)
tmp = pgprot_decrypted(tmp);
} else {
caching = res->bus.caching;
}
return ttm_prot_from_caching(caching, tmp);
}
@@ -337,6 +343,8 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo,
.no_wait_gpu = false
};
struct ttm_tt *ttm = bo->ttm;
struct ttm_resource_manager *man =
ttm_manager_type(bo->bdev, bo->resource->mem_type);
pgprot_t prot;
int ret;
@@ -346,7 +354,8 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo,
if (ret)
return ret;
if (num_pages == 1 && ttm->caching == ttm_cached) {
if (num_pages == 1 && ttm->caching == ttm_cached &&
!(man->use_tt && (ttm->page_flags & TTM_TT_FLAG_DECRYPTED))) {
/*
* We're mapping a single page, and the desired
* page protection is consistent with the bo.
+16 -57
View File
@@ -291,37 +291,15 @@ bool ttm_resource_intersects(struct ttm_device *bdev,
}
/**
* ttm_resource_compatible - test for compatibility
* ttm_resource_compatible - check if resource is compatible with placement
*
* @bdev: TTM device structure
* @res: The resource to test
* @place: The placement to test
* @size: How many bytes the new allocation needs.
* @res: the resource to check
* @placement: the placement to check against
*
* Test if @res compatible with @place and @size.
*
* Returns true if the res placement compatible with @place and @size.
* Returns true if the placement is compatible.
*/
bool ttm_resource_compatible(struct ttm_device *bdev,
struct ttm_resource *res,
const struct ttm_place *place,
size_t size)
{
struct ttm_resource_manager *man;
if (!res || !place)
return false;
man = ttm_manager_type(bdev, res->mem_type);
if (!man->func->compatible)
return true;
return man->func->compatible(man, res, place, size);
}
static bool ttm_resource_places_compat(struct ttm_resource *res,
const struct ttm_place *places,
unsigned num_placement)
bool ttm_resource_compatible(struct ttm_resource *res,
struct ttm_placement *placement)
{
struct ttm_buffer_object *bo = res->bo;
struct ttm_device *bdev = bo->bdev;
@@ -330,44 +308,25 @@ static bool ttm_resource_places_compat(struct ttm_resource *res,
if (res->placement & TTM_PL_FLAG_TEMPORARY)
return false;
for (i = 0; i < num_placement; i++) {
const struct ttm_place *heap = &places[i];
for (i = 0; i < placement->num_placement; i++) {
const struct ttm_place *place = &placement->placement[i];
struct ttm_resource_manager *man;
if (!ttm_resource_compatible(bdev, res, heap, bo->base.size))
if (res->mem_type != place->mem_type)
continue;
if ((res->mem_type == heap->mem_type) &&
(!(heap->flags & TTM_PL_FLAG_CONTIGUOUS) ||
man = ttm_manager_type(bdev, res->mem_type);
if (man->func->compatible &&
!man->func->compatible(man, res, place, bo->base.size))
continue;
if ((!(place->flags & TTM_PL_FLAG_CONTIGUOUS) ||
(res->placement & TTM_PL_FLAG_CONTIGUOUS)))
return true;
}
return false;
}
/**
* ttm_resource_compat - check if resource is compatible with placement
*
* @res: the resource to check
* @placement: the placement to check against
*
* Returns true if the placement is compatible.
*/
bool ttm_resource_compat(struct ttm_resource *res,
struct ttm_placement *placement)
{
if (ttm_resource_places_compat(res, placement->placement,
placement->num_placement))
return true;
if ((placement->busy_placement != placement->placement ||
placement->num_busy_placement > placement->num_placement) &&
ttm_resource_places_compat(res, placement->busy_placement,
placement->num_busy_placement))
return true;
return false;
}
void ttm_resource_set_bo(struct ttm_resource *res,
struct ttm_buffer_object *bo)
{
+12
View File
@@ -31,11 +31,13 @@
#define pr_fmt(fmt) "[TTM] " fmt
#include <linux/cc_platform.h>
#include <linux/sched.h>
#include <linux/shmem_fs.h>
#include <linux/file.h>
#include <linux/module.h>
#include <drm/drm_cache.h>
#include <drm/drm_device.h>
#include <drm/drm_util.h>
#include <drm/ttm/ttm_bo.h>
#include <drm/ttm/ttm_tt.h>
@@ -61,6 +63,7 @@ static atomic_long_t ttm_dma32_pages_allocated;
int ttm_tt_create(struct ttm_buffer_object *bo, bool zero_alloc)
{
struct ttm_device *bdev = bo->bdev;
struct drm_device *ddev = bo->base.dev;
uint32_t page_flags = 0;
dma_resv_assert_held(bo->base.resv);
@@ -82,6 +85,15 @@ int ttm_tt_create(struct ttm_buffer_object *bo, bool zero_alloc)
pr_err("Illegal buffer object type\n");
return -EINVAL;
}
/*
* When using dma_alloc_coherent with memory encryption the
* mapped TT pages need to be decrypted or otherwise the drivers
* will end up sending encrypted mem to the gpu.
*/
if (bdev->pool.use_dma_alloc && cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
page_flags |= TTM_TT_FLAG_DECRYPTED;
drm_info(ddev, "TT memory decryption enabled.");
}
bo->ttm = bdev->funcs->ttm_tt_create(bo, page_flags);
if (unlikely(bo->ttm == NULL))
-1
View File
@@ -9,7 +9,6 @@ config DRM_TVE200
select DRM_PANEL_BRIDGE
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
help
Choose this option for DRM support for the Faraday TV Encoder
TVE200 Controller.
+1
View File
@@ -35,6 +35,7 @@
#include <drm/display/drm_scdc_helper.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_edid.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_simple_kms_helper.h>
#include <linux/clk.h>
+3 -3
View File
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR MIT */
/**************************************************************************
*
* Copyright (c) 2009-2022 VMware, Inc., Palo Alto, CA., USA
* Copyright (c) 2009-2023 VMware, Inc., Palo Alto, CA., USA
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -648,7 +648,6 @@ out_unref:
* @tfile: struct ttm_object_file identifying the caller
* @size: The size of the dma_bufs we export.
* @prime: The object to be initialized.
* @shareable: See ttm_base_object_init
* @type: See ttm_base_object_init
* @refcount_release: See ttm_base_object_init
*
@@ -656,10 +655,11 @@ out_unref:
* for data sharing between processes and devices.
*/
int ttm_prime_object_init(struct ttm_object_file *tfile, size_t size,
struct ttm_prime_object *prime, bool shareable,
struct ttm_prime_object *prime,
enum ttm_object_type type,
void (*refcount_release) (struct ttm_base_object **))
{
bool shareable = !!(type == VMW_RES_SURFACE);
mutex_init(&prime->mutex);
prime->size = PAGE_ALIGN(size);
prime->real_type = type;
+1 -2
View File
@@ -1,6 +1,6 @@
/**************************************************************************
*
* Copyright (c) 2006-2022 VMware, Inc., Palo Alto, CA., USA
* Copyright (c) 2006-2023 VMware, Inc., Palo Alto, CA., USA
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -288,7 +288,6 @@ extern void ttm_object_device_release(struct ttm_object_device **p_tdev);
extern int ttm_prime_object_init(struct ttm_object_file *tfile,
size_t size,
struct ttm_prime_object *prime,
bool shareable,
enum ttm_object_type type,
void (*refcount_release)
(struct ttm_base_object **));
+25 -10
View File
@@ -742,9 +742,21 @@ void vmw_bo_move_notify(struct ttm_buffer_object *bo,
vmw_resource_unbind_list(vbo);
}
static u32
set_placement_list(struct ttm_place *pl, u32 domain)
static u32 placement_flags(u32 domain, u32 desired, u32 fallback)
{
if (desired & fallback & domain)
return 0;
if (desired & domain)
return TTM_PL_FLAG_DESIRED;
return TTM_PL_FLAG_FALLBACK;
}
static u32
set_placement_list(struct ttm_place *pl, u32 desired, u32 fallback)
{
u32 domain = desired | fallback;
u32 n = 0;
/*
@@ -752,35 +764,40 @@ set_placement_list(struct ttm_place *pl, u32 domain)
*/
if (domain & VMW_BO_DOMAIN_MOB) {
pl[n].mem_type = VMW_PL_MOB;
pl[n].flags = 0;
pl[n].flags = placement_flags(VMW_BO_DOMAIN_MOB, desired,
fallback);
pl[n].fpfn = 0;
pl[n].lpfn = 0;
n++;
}
if (domain & VMW_BO_DOMAIN_GMR) {
pl[n].mem_type = VMW_PL_GMR;
pl[n].flags = 0;
pl[n].flags = placement_flags(VMW_BO_DOMAIN_GMR, desired,
fallback);
pl[n].fpfn = 0;
pl[n].lpfn = 0;
n++;
}
if (domain & VMW_BO_DOMAIN_VRAM) {
pl[n].mem_type = TTM_PL_VRAM;
pl[n].flags = 0;
pl[n].flags = placement_flags(VMW_BO_DOMAIN_VRAM, desired,
fallback);
pl[n].fpfn = 0;
pl[n].lpfn = 0;
n++;
}
if (domain & VMW_BO_DOMAIN_WAITABLE_SYS) {
pl[n].mem_type = VMW_PL_SYSTEM;
pl[n].flags = 0;
pl[n].flags = placement_flags(VMW_BO_DOMAIN_WAITABLE_SYS,
desired, fallback);
pl[n].fpfn = 0;
pl[n].lpfn = 0;
n++;
}
if (domain & VMW_BO_DOMAIN_SYS) {
pl[n].mem_type = TTM_PL_SYSTEM;
pl[n].flags = 0;
pl[n].flags = placement_flags(VMW_BO_DOMAIN_SYS, desired,
fallback);
pl[n].fpfn = 0;
pl[n].lpfn = 0;
n++;
@@ -806,7 +823,7 @@ void vmw_bo_placement_set(struct vmw_bo *bo, u32 domain, u32 busy_domain)
u32 i;
pl->placement = bo->places;
pl->num_placement = set_placement_list(bo->places, domain);
pl->num_placement = set_placement_list(bo->places, domain, busy_domain);
if (drm_debug_enabled(DRM_UT_DRIVER) && bo->tbo.resource) {
for (i = 0; i < pl->num_placement; ++i) {
@@ -821,8 +838,6 @@ void vmw_bo_placement_set(struct vmw_bo *bo, u32 domain, u32 busy_domain)
__func__, bo->tbo.resource->mem_type, domain);
}
pl->busy_placement = bo->busy_places;
pl->num_busy_placement = set_placement_list(bo->busy_places, busy_domain);
}
void vmw_bo_placement_set_default_accelerated(struct vmw_bo *bo)

Some files were not shown because too many files have changed in this diff Show More