summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/imx
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-11-21 14:56:17 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2024-11-21 14:56:17 -0800
commit28eb75e178d389d325f1666e422bc13bbbb9804c (patch)
tree20417b4e798f98fc5687e80c1e0126afcf437c70 /drivers/gpu/drm/imx
parent071b34dcf71523a559b6c39f5d21a268a9531b50 (diff)
parenta163b895077861598be48c1cf7f4a88413c28b22 (diff)
Merge tag 'drm-next-2024-11-21' of https://gitlab.freedesktop.org/drm/kernel
Pull drm updates from Dave Airlie: "There's a lot of rework, the panic helper support is being added to more drivers, v3d gets support for HW superpages, scheduler documentation, drm client and video aperture reworks, some new MAINTAINERS added, amdgpu has the usual lots of IP refactors, Intel has some Pantherlake enablement and xe is getting some SRIOV bits, but just lots of stuff everywhere. core: - split DSC helpers from DP helpers - clang build fixes for drm/mm test - drop simple pipeline support for gem vram - document submission error signaling - move drm_rect to drm core module from kms helper - add default client setup to most drivers - move to video aperture helpers instead of drm ones tests: - new framebuffer tests ttm: - remove swapped and pinned BOs from TTM lru panic: - fix uninit spinlock - add ABGR2101010 support bridge: - add TI TDP158 support - use standard PM OPS dma-fence: - use read_trylock instead of read_lock to help lockdep scheduler: - add errno to sched start to report different errors - add locking to drm_sched_entity_modify_sched - improve documentation xe: - add drm_line_printer - lots of refactoring - Enable Xe2 + PES disaggregation - add new ARL PCI ID - SRIOV development work - fix exec unnecessary implicit fence - define and parse OA sync props - forcewake refactoring i915: - Enable BMG/LNL ultra joiner - Enable 10bpx + CCS scanout on ICL+, fp16/CCS on TGL+ - use DSB for plane/color mgmt - Arrow lake PCI IDs - lots of i915/xe display refactoring - enable PXP GuC autoteardown - Pantherlake (PTL) Xe3 LPD display enablement - Allow fastset HDR infoframe changes - write DP source OUI for non-eDP sinks - share PCI IDs between i915 and xe amdgpu: - SDMA queue reset support - SMU 13.0.6, JPEG 4.0.3 updates - Initial runtime repartitioning support - rework IP structs for multiple IP instances - Fetch EDID from _DDC if available - SMU13 zero rpm user control - lots of fixes/cleanups amdkfd: - Increase event FIFO size - add topology cap flag for per queue reset msm: - DPU: - SA8775P support - (disabled by default) MSM8917, MSM8937, MSM8953 and MSM8996 support - Enable large framebuffer support - Drop MSM8998 and SDM845 - DP: - SA8775P support - GPU: - a7xx preemption support - Adreno A663 support ast: - warn about unsupported TX chips ivpu: - add coredump - add pantherlake support rockchip: - 4K@60Hz display enablement - generate pll programming tables panthor: - add timestamp query API - add realtime group priority - add fdinfo support etnaviv: - improve handling of DMA address limits - improve GPU hangcheck exynos: - Decon Exynos7870 support mediatek: - add OF graph support omap: - locking fixes bochs: - convert to gem/shmem from simpledrm v3d: - support big/super pages - add gemfs vc4: - BCM2712 support refactoring - add YUV444 format support udmabuf: - folio related fixes nouveau: - add panic support on nv50+" * tag 'drm-next-2024-11-21' of https://gitlab.freedesktop.org/drm/kernel: (1583 commits) drm/xe/guc: Fix dereference before NULL check drm/amd: Fix initialization mistake for NBIO 7.7.0 Revert "drm/amd/display: parse umc_info or vram_info based on ASIC" drm/amd/display: Fix failure to read vram info due to static BP_RESULT drm/amdgpu: enable GTT fallback handling for dGPUs only drm/amd/amdgpu: limit single process inside MES drm/fourcc: add AMD_FMT_MOD_TILE_GFX9_4K_D_X drm/amdgpu/mes12: correct kiq unmap latency drm/amdgpu: Support vcn and jpeg error info parsing drm/amd : Update MES API header file for v11 & v12 drm/amd/amdkfd: add/remove kfd queues on start/stop KFD scheduling drm/amdkfd: change kfd process kref count at creation drm/amdgpu: Cleanup shift coding style drm/amd/amdgpu: Increase MES log buffer to dump mes scratch data drm/amdgpu: Implement virt req_ras_err_count drm/amdgpu: VF Query RAS Caps from Host if supported drm/amdgpu: Add msg handlers for SRIOV RAS Telemetry drm/amdgpu: Update SRIOV Exchange Headers for RAS Telemetry Support drm/amd/display: 3.2.309 drm/amd/display: Adjust VSDB parser for replay feature ...
Diffstat (limited to 'drivers/gpu/drm/imx')
-rw-r--r--drivers/gpu/drm/imx/dcss/Kconfig3
-rw-r--r--drivers/gpu/drm/imx/dcss/dcss-crtc.c6
-rw-r--r--drivers/gpu/drm/imx/dcss/dcss-dtg.c4
-rw-r--r--drivers/gpu/drm/imx/dcss/dcss-kms.c5
-rw-r--r--drivers/gpu/drm/imx/dcss/dcss-scaler.c4
-rw-r--r--drivers/gpu/drm/imx/ipuv3/Kconfig14
-rw-r--r--drivers/gpu/drm/imx/ipuv3/imx-drm-core.c11
-rw-r--r--drivers/gpu/drm/imx/ipuv3/imx-drm.h14
-rw-r--r--drivers/gpu/drm/imx/ipuv3/imx-ldb.c203
-rw-r--r--drivers/gpu/drm/imx/ipuv3/imx-tve.c8
-rw-r--r--drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c6
-rw-r--r--drivers/gpu/drm/imx/ipuv3/parallel-display.c143
-rw-r--r--drivers/gpu/drm/imx/lcdc/Kconfig1
-rw-r--r--drivers/gpu/drm/imx/lcdc/imx-lcdc.c4
14 files changed, 102 insertions, 324 deletions
diff --git a/drivers/gpu/drm/imx/dcss/Kconfig b/drivers/gpu/drm/imx/dcss/Kconfig
index 59e3b6a1dff06..e014ed3ae66c9 100644
--- a/drivers/gpu/drm/imx/dcss/Kconfig
+++ b/drivers/gpu/drm/imx/dcss/Kconfig
@@ -1,12 +1,13 @@
config DRM_IMX_DCSS
tristate "i.MX8MQ DCSS"
select IMX_IRQSTEER
+ select DRM_CLIENT_SELECTION
select DRM_KMS_HELPER
select DRM_DISPLAY_HELPER
select DRM_BRIDGE_CONNECTOR
select DRM_GEM_DMA_HELPER
select VIDEOMODE_HELPERS
- depends on DRM && ARCH_MXC && ARM64
+ depends on DRM && ((ARCH_MXC && ARM64) || COMPILE_TEST)
help
Choose this if you have a NXP i.MX8MQ based system and want to use the
Display Controller Subsystem. This option enables DCSS support.
diff --git a/drivers/gpu/drm/imx/dcss/dcss-crtc.c b/drivers/gpu/drm/imx/dcss/dcss-crtc.c
index 31267c00782fc..af91e45b5d13b 100644
--- a/drivers/gpu/drm/imx/dcss/dcss-crtc.c
+++ b/drivers/gpu/drm/imx/dcss/dcss-crtc.c
@@ -206,15 +206,13 @@ int dcss_crtc_init(struct dcss_crtc *crtc, struct drm_device *drm)
if (crtc->irq < 0)
return crtc->irq;
- ret = request_irq(crtc->irq, dcss_crtc_irq_handler,
- 0, "dcss_drm", crtc);
+ ret = request_irq(crtc->irq, dcss_crtc_irq_handler, IRQF_NO_AUTOEN,
+ "dcss_drm", crtc);
if (ret) {
dev_err(dcss->dev, "irq request failed with %d.\n", ret);
return ret;
}
- disable_irq(crtc->irq);
-
return 0;
}
diff --git a/drivers/gpu/drm/imx/dcss/dcss-dtg.c b/drivers/gpu/drm/imx/dcss/dcss-dtg.c
index 2968f5d5bd412..6bbfd9aa27aca 100644
--- a/drivers/gpu/drm/imx/dcss/dcss-dtg.c
+++ b/drivers/gpu/drm/imx/dcss/dcss-dtg.c
@@ -134,14 +134,12 @@ static int dcss_dtg_irq_config(struct dcss_dtg *dtg,
dtg->base_reg + DCSS_DTG_INT_MASK);
ret = request_irq(dtg->ctxld_kick_irq, dcss_dtg_irq_handler,
- 0, "dcss_ctxld_kick", dtg);
+ IRQF_NO_AUTOEN, "dcss_ctxld_kick", dtg);
if (ret) {
dev_err(dtg->dev, "dtg: irq request failed.\n");
return ret;
}
- disable_irq(dtg->ctxld_kick_irq);
-
dtg->ctxld_kick_irq_en = false;
return 0;
diff --git a/drivers/gpu/drm/imx/dcss/dcss-kms.c b/drivers/gpu/drm/imx/dcss/dcss-kms.c
index d0ea4e97cded6..63a335c62296e 100644
--- a/drivers/gpu/drm/imx/dcss/dcss-kms.c
+++ b/drivers/gpu/drm/imx/dcss/dcss-kms.c
@@ -5,7 +5,9 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
#include <drm/drm_bridge_connector.h>
+#include <drm/drm_client_setup.h>
#include <drm/drm_drv.h>
#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_dma_helper.h>
@@ -28,6 +30,7 @@ static const struct drm_mode_config_funcs dcss_drm_mode_config_funcs = {
static const struct drm_driver dcss_kms_driver = {
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
DRM_GEM_DMA_DRIVER_OPS,
+ DRM_FBDEV_DMA_DRIVER_OPS,
.fops = &dcss_cma_fops,
.name = "imx-dcss",
.desc = "i.MX8MQ Display Subsystem",
@@ -145,7 +148,7 @@ struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss)
if (ret)
goto cleanup_crtc;
- drm_fbdev_dma_setup(drm, 32);
+ drm_client_setup(drm, NULL);
return kms;
diff --git a/drivers/gpu/drm/imx/dcss/dcss-scaler.c b/drivers/gpu/drm/imx/dcss/dcss-scaler.c
index 825728c356ffb..32c3f46b21dae 100644
--- a/drivers/gpu/drm/imx/dcss/dcss-scaler.c
+++ b/drivers/gpu/drm/imx/dcss/dcss-scaler.c
@@ -136,7 +136,7 @@ static int div_q(int A, int B)
else
temp -= B / 2;
- result = (int)(temp / B);
+ result = div_s64(temp, B);
return result;
}
@@ -239,7 +239,7 @@ static void dcss_scaler_gaussian_filter(int fc_q, bool use_5_taps,
ll_temp = coef[phase][i];
ll_temp <<= PSC_COEFF_PRECISION;
ll_temp += sum >> 1;
- ll_temp /= sum;
+ ll_temp = div_s64(ll_temp, sum);
coef[phase][i] = (int)ll_temp;
}
}
diff --git a/drivers/gpu/drm/imx/ipuv3/Kconfig b/drivers/gpu/drm/imx/ipuv3/Kconfig
index bacf0655ebaf3..acaf250890019 100644
--- a/drivers/gpu/drm/imx/ipuv3/Kconfig
+++ b/drivers/gpu/drm/imx/ipuv3/Kconfig
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config DRM_IMX
tristate "DRM Support for Freescale i.MX"
+ select DRM_CLIENT_SELECTION
select DRM_KMS_HELPER
select VIDEOMODE_HELPERS
select DRM_GEM_DMA_HELPER
@@ -11,8 +12,11 @@ config DRM_IMX
config DRM_IMX_PARALLEL_DISPLAY
tristate "Support for parallel displays"
- select DRM_PANEL
depends on DRM_IMX
+ select DRM_BRIDGE
+ select DRM_BRIDGE_CONNECTOR
+ select DRM_IMX_LEGACY_BRIDGE
+ select DRM_PANEL_BRIDGE
select VIDEOMODE_HELPERS
config DRM_IMX_TVE
@@ -26,9 +30,13 @@ config DRM_IMX_TVE
config DRM_IMX_LDB
tristate "Support for LVDS displays"
- depends on DRM_IMX && MFD_SYSCON
+ depends on DRM_IMX
depends on COMMON_CLK
- select DRM_PANEL
+ select MFD_SYSCON
+ select DRM_BRIDGE
+ select DRM_BRIDGE_CONNECTOR
+ select DRM_PANEL_BRIDGE
+ select DRM_IMX_LEGACY_BRIDGE
help
Choose this to enable the internal LVDS Display Bridge (LDB)
found on i.MX53 and i.MX6 processors.
diff --git a/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c b/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c
index 4cfabcf7375a9..ced06bd8eae8b 100644
--- a/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c
@@ -15,6 +15,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
+#include <drm/drm_client_setup.h>
#include <drm/drm_drv.h>
#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_dma_helper.h>
@@ -34,13 +35,6 @@ module_param(legacyfb_depth, int, 0444);
DEFINE_DRM_GEM_DMA_FOPS(imx_drm_driver_fops);
-void imx_drm_connector_destroy(struct drm_connector *connector)
-{
- drm_connector_unregister(connector);
- drm_connector_cleanup(connector);
-}
-EXPORT_SYMBOL_GPL(imx_drm_connector_destroy);
-
static int imx_drm_atomic_check(struct drm_device *dev,
struct drm_atomic_state *state)
{
@@ -163,6 +157,7 @@ static int imx_drm_dumb_create(struct drm_file *file_priv,
static const struct drm_driver imx_drm_driver = {
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(imx_drm_dumb_create),
+ DRM_FBDEV_DMA_DRIVER_OPS,
.ioctls = imx_drm_ioctls,
.num_ioctls = ARRAY_SIZE(imx_drm_ioctls),
.fops = &imx_drm_driver_fops,
@@ -249,7 +244,7 @@ static int imx_drm_bind(struct device *dev)
if (ret)
goto err_poll_fini;
- drm_fbdev_dma_setup(drm, legacyfb_depth);
+ drm_client_setup_with_color_mode(drm, legacyfb_depth);
return 0;
diff --git a/drivers/gpu/drm/imx/ipuv3/imx-drm.h b/drivers/gpu/drm/imx/ipuv3/imx-drm.h
index e721bebda2bdd..0c85bf83ffbff 100644
--- a/drivers/gpu/drm/imx/ipuv3/imx-drm.h
+++ b/drivers/gpu/drm/imx/ipuv3/imx-drm.h
@@ -3,14 +3,9 @@
#define _IMX_DRM_H_
struct device_node;
-struct drm_crtc;
struct drm_connector;
struct drm_device;
-struct drm_display_mode;
struct drm_encoder;
-struct drm_framebuffer;
-struct drm_plane;
-struct platform_device;
struct imx_crtc_state {
struct drm_crtc_state base;
@@ -24,21 +19,12 @@ static inline struct imx_crtc_state *to_imx_crtc_state(struct drm_crtc_state *s)
{
return container_of(s, struct imx_crtc_state, base);
}
-int imx_drm_init_drm(struct platform_device *pdev,
- int preferred_bpp);
-int imx_drm_exit_drm(void);
extern struct platform_driver ipu_drm_driver;
-void imx_drm_mode_config_init(struct drm_device *drm);
-
-struct drm_gem_dma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb);
-
int imx_drm_encoder_parse_of(struct drm_device *drm,
struct drm_encoder *encoder, struct device_node *np);
-void imx_drm_connector_destroy(struct drm_connector *connector);
-
int ipu_planes_assign_pre(struct drm_device *dev,
struct drm_atomic_state *state);
diff --git a/drivers/gpu/drm/imx/ipuv3/imx-ldb.c b/drivers/gpu/drm/imx/ipuv3/imx-ldb.c
index 793dfb1a3ed00..ff74018ac5cdf 100644
--- a/drivers/gpu/drm/imx/ipuv3/imx-ldb.c
+++ b/drivers/gpu/drm/imx/ipuv3/imx-ldb.c
@@ -19,19 +19,16 @@
#include <linux/regmap.h>
#include <linux/videodev2.h>
-#include <video/of_display_timing.h>
-#include <video/of_videomode.h>
-
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
-#include <drm/drm_edid.h>
+#include <drm/drm_bridge_connector.h>
#include <drm/drm_managed.h>
#include <drm/drm_of.h>
-#include <drm/drm_panel.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_simple_kms_helper.h>
+#include <drm/bridge/imx.h>
#include "imx-drm.h"
@@ -55,7 +52,6 @@
struct imx_ldb_channel;
struct imx_ldb_encoder {
- struct drm_connector connector;
struct drm_encoder encoder;
struct imx_ldb_channel *channel;
};
@@ -65,25 +61,13 @@ struct imx_ldb;
struct imx_ldb_channel {
struct imx_ldb *ldb;
- /* Defines what is connected to the ldb, only one at a time */
- struct drm_panel *panel;
struct drm_bridge *bridge;
struct device_node *child;
- struct i2c_adapter *ddc;
int chno;
- const struct drm_edid *drm_edid;
- struct drm_display_mode mode;
- int mode_valid;
u32 bus_format;
- u32 bus_flags;
};
-static inline struct imx_ldb_channel *con_to_imx_ldb_ch(struct drm_connector *c)
-{
- return container_of(c, struct imx_ldb_encoder, connector)->channel;
-}
-
static inline struct imx_ldb_channel *enc_to_imx_ldb_ch(struct drm_encoder *e)
{
return container_of(e, struct imx_ldb_encoder, encoder)->channel;
@@ -133,38 +117,6 @@ static void imx_ldb_ch_set_bus_format(struct imx_ldb_channel *imx_ldb_ch,
}
}
-static int imx_ldb_connector_get_modes(struct drm_connector *connector)
-{
- struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
- int num_modes;
-
- num_modes = drm_panel_get_modes(imx_ldb_ch->panel, connector);
- if (num_modes > 0)
- return num_modes;
-
- if (!imx_ldb_ch->drm_edid && imx_ldb_ch->ddc) {
- imx_ldb_ch->drm_edid = drm_edid_read_ddc(connector,
- imx_ldb_ch->ddc);
- drm_edid_connector_update(connector, imx_ldb_ch->drm_edid);
- }
-
- if (imx_ldb_ch->drm_edid)
- num_modes = drm_edid_connector_add_modes(connector);
-
- if (imx_ldb_ch->mode_valid) {
- struct drm_display_mode *mode;
-
- mode = drm_mode_duplicate(connector->dev, &imx_ldb_ch->mode);
- if (!mode)
- return -EINVAL;
- mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
- drm_mode_probed_add(connector, mode);
- num_modes++;
- }
-
- return num_modes;
-}
-
static void imx_ldb_set_clock(struct imx_ldb *ldb, int mux, int chno,
unsigned long serial_clk, unsigned long di_clk)
{
@@ -205,8 +157,6 @@ static void imx_ldb_encoder_enable(struct drm_encoder *encoder)
return;
}
- drm_panel_prepare(imx_ldb_ch->panel);
-
if (dual) {
clk_set_parent(ldb->clk_sel[mux], ldb->clk[0]);
clk_set_parent(ldb->clk_sel[mux], ldb->clk[1]);
@@ -245,8 +195,6 @@ static void imx_ldb_encoder_enable(struct drm_encoder *encoder)
}
regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl);
-
- drm_panel_enable(imx_ldb_ch->panel);
}
static void
@@ -323,8 +271,6 @@ static void imx_ldb_encoder_disable(struct drm_encoder *encoder)
int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
int mux, ret;
- drm_panel_disable(imx_ldb_ch->panel);
-
if (imx_ldb_ch == &ldb->channel[0] || dual)
ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK;
if (imx_ldb_ch == &ldb->channel[1] || dual)
@@ -358,8 +304,6 @@ static void imx_ldb_encoder_disable(struct drm_encoder *encoder)
dev_err(ldb->dev,
"unable to set di%d parent clock to original parent\n",
mux);
-
- drm_panel_unprepare(imx_ldb_ch->panel);
}
static int imx_ldb_encoder_atomic_check(struct drm_encoder *encoder,
@@ -374,11 +318,12 @@ static int imx_ldb_encoder_atomic_check(struct drm_encoder *encoder,
/* Bus format description in DT overrides connector display info. */
if (!bus_format && di->num_bus_formats) {
bus_format = di->bus_formats[0];
- imx_crtc_state->bus_flags = di->bus_flags;
} else {
bus_format = imx_ldb_ch->bus_format;
- imx_crtc_state->bus_flags = imx_ldb_ch->bus_flags;
}
+
+ imx_crtc_state->bus_flags = di->bus_flags;
+
switch (bus_format) {
case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
imx_crtc_state->bus_format = MEDIA_BUS_FMT_RGB666_1X18;
@@ -398,18 +343,6 @@ static int imx_ldb_encoder_atomic_check(struct drm_encoder *encoder,
}
-static const struct drm_connector_funcs imx_ldb_connector_funcs = {
- .fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = imx_drm_connector_destroy,
- .reset = drm_atomic_helper_connector_reset,
- .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
-
-static const struct drm_connector_helper_funcs imx_ldb_connector_helper_funcs = {
- .get_modes = imx_ldb_connector_get_modes,
-};
-
static const struct drm_encoder_helper_funcs imx_ldb_encoder_helper_funcs = {
.atomic_mode_set = imx_ldb_encoder_atomic_mode_set,
.enable = imx_ldb_encoder_enable,
@@ -447,7 +380,6 @@ static int imx_ldb_register(struct drm_device *drm,
return PTR_ERR(ldb_encoder);
ldb_encoder->channel = imx_ldb_ch;
- connector = &ldb_encoder->connector;
encoder = &ldb_encoder->encoder;
ret = imx_drm_encoder_parse_of(drm, encoder, imx_ldb_ch->child);
@@ -466,25 +398,16 @@ static int imx_ldb_register(struct drm_device *drm,
drm_encoder_helper_add(encoder, &imx_ldb_encoder_helper_funcs);
- if (imx_ldb_ch->bridge) {
- ret = drm_bridge_attach(encoder, imx_ldb_ch->bridge, NULL, 0);
- if (ret)
- return ret;
- } else {
- /*
- * We want to add the connector whenever there is no bridge
- * that brings its own, not only when there is a panel. For
- * historical reasons, the ldb driver can also work without
- * a panel.
- */
- drm_connector_helper_add(connector,
- &imx_ldb_connector_helper_funcs);
- drm_connector_init_with_ddc(drm, connector,
- &imx_ldb_connector_funcs,
- DRM_MODE_CONNECTOR_LVDS,
- imx_ldb_ch->ddc);
- drm_connector_attach_encoder(connector, encoder);
- }
+ ret = drm_bridge_attach(encoder, imx_ldb_ch->bridge, NULL,
+ DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+ if (ret)
+ return ret;
+
+ connector = drm_bridge_connector_init(drm, encoder);
+ if (IS_ERR(connector))
+ return PTR_ERR(connector);
+
+ drm_connector_attach_encoder(connector, encoder);
return 0;
}
@@ -549,47 +472,6 @@ static const struct of_device_id imx_ldb_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, imx_ldb_dt_ids);
-static int imx_ldb_panel_ddc(struct device *dev,
- struct imx_ldb_channel *channel, struct device_node *child)
-{
- struct device_node *ddc_node;
- int ret;
-
- ddc_node = of_parse_phandle(child, "ddc-i2c-bus", 0);
- if (ddc_node) {
- channel->ddc = of_find_i2c_adapter_by_node(ddc_node);
- of_node_put(ddc_node);
- if (!channel->ddc) {
- dev_warn(dev, "failed to get ddc i2c adapter\n");
- return -EPROBE_DEFER;
- }
- }
-
- if (!channel->ddc) {
- const void *edidp;
- int edid_len;
-
- /* if no DDC available, fallback to hardcoded EDID */
- dev_dbg(dev, "no ddc available\n");
-
- edidp = of_get_property(child, "edid", &edid_len);
- if (edidp) {
- channel->drm_edid = drm_edid_alloc(edidp, edid_len);
- if (!channel->drm_edid)
- return -ENOMEM;
- } else if (!channel->panel) {
- /* fallback to display-timings node */
- ret = of_get_drm_display_mode(child,
- &channel->mode,
- &channel->bus_flags,
- OF_USE_NATIVE_MODE);
- if (!ret)
- channel->mode_valid = 1;
- }
- }
- return 0;
-}
-
static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
{
struct drm_device *drm = data;
@@ -694,29 +576,22 @@ static int imx_ldb_probe(struct platform_device *pdev)
* The output port is port@4 with an external 4-port mux or
* port@2 with the internal 2-port mux.
*/
- ret = drm_of_find_panel_or_bridge(child,
- imx_ldb->lvds_mux ? 4 : 2, 0,
- &channel->panel, &channel->bridge);
- if (ret && ret != -ENODEV)
- goto free_child;
-
- /* panel ddc only if there is no bridge */
- if (!channel->bridge) {
- ret = imx_ldb_panel_ddc(dev, channel, child);
- if (ret)
+ channel->bridge = devm_drm_of_get_bridge(dev, child,
+ imx_ldb->lvds_mux ? 4 : 2, 0);
+ if (IS_ERR(channel->bridge)) {
+ ret = PTR_ERR(channel->bridge);
+ if (ret != -ENODEV)
goto free_child;
+ channel->bridge = NULL;
}
bus_format = of_get_bus_format(dev, child);
- if (bus_format == -EINVAL) {
- /*
- * If no bus format was specified in the device tree,
- * we can still get it from the connected panel later.
- */
- if (channel->panel && channel->panel->funcs &&
- channel->panel->funcs->get_modes)
- bus_format = 0;
- }
+ /*
+ * If no bus format was specified in the device tree,
+ * we can still get it from the connected panel later.
+ */
+ if (bus_format == -EINVAL && channel->bridge)
+ bus_format = 0;
if (bus_format < 0) {
dev_err(dev, "could not determine data mapping: %d\n",
bus_format);
@@ -724,6 +599,20 @@ static int imx_ldb_probe(struct platform_device *pdev)
goto free_child;
}
channel->bus_format = bus_format;
+
+ /*
+ * legacy bridge doesn't handle bus_format, so create it after
+ * checking the bus_format property.
+ */
+ if (!channel->bridge) {
+ channel->bridge = devm_imx_drm_legacy_bridge(dev, child,
+ DRM_MODE_CONNECTOR_LVDS);
+ if (IS_ERR(channel->bridge)) {
+ ret = PTR_ERR(channel->bridge);
+ goto free_child;
+ }
+ }
+
channel->child = child;
}
@@ -738,16 +627,6 @@ free_child:
static void imx_ldb_remove(struct platform_device *pdev)
{
- struct imx_ldb *imx_ldb = platform_get_drvdata(pdev);
- int i;
-
- for (i = 0; i < 2; i++) {
- struct imx_ldb_channel *channel = &imx_ldb->channel[i];
-
- drm_edid_free(channel->drm_edid);
- i2c_put_adapter(channel->ddc);
- }
-
component_del(&pdev->dev, &imx_ldb_ops);
}
diff --git a/drivers/gpu/drm/imx/ipuv3/imx-tve.c b/drivers/gpu/drm/imx/ipuv3/imx-tve.c
index 29f494bfff67d..d46d07d25f517 100644
--- a/drivers/gpu/drm/imx/ipuv3/imx-tve.c
+++ b/drivers/gpu/drm/imx/ipuv3/imx-tve.c
@@ -305,9 +305,15 @@ static int imx_tve_atomic_check(struct drm_encoder *encoder,
return 0;
}
+static void imx_tve_connector_destroy(struct drm_connector *connector)
+{
+ drm_connector_unregister(connector);
+ drm_connector_cleanup(connector);
+}
+
static const struct drm_connector_funcs imx_tve_connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = imx_drm_connector_destroy,
+ .destroy = imx_tve_connector_destroy,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
diff --git a/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c
index ef29c9a61a461..99db53e167bd0 100644
--- a/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c
+++ b/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c
@@ -410,14 +410,12 @@ static int ipu_drm_bind(struct device *dev, struct device *master, void *data)
}
ipu_crtc->irq = ipu_plane_irq(ipu_crtc->plane[0]);
- ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler, 0,
- "imx_drm", ipu_crtc);
+ ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler,
+ IRQF_NO_AUTOEN, "imx_drm", ipu_crtc);
if (ret < 0) {
dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret);
return ret;
}
- /* Only enable IRQ when we actually need it to trigger work. */
- disable_irq(ipu_crtc->irq);
return 0;
}
diff --git a/drivers/gpu/drm/imx/ipuv3/parallel-display.c b/drivers/gpu/drm/imx/ipuv3/parallel-display.c
index 91d7808a2d8d3..70f62e89622e5 100644
--- a/drivers/gpu/drm/imx/ipuv3/parallel-display.c
+++ b/drivers/gpu/drm/imx/ipuv3/parallel-display.c
@@ -12,21 +12,18 @@
#include <linux/platform_device.h>
#include <linux/videodev2.h>
-#include <video/of_display_timing.h>
-
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
-#include <drm/drm_edid.h>
+#include <drm/drm_bridge_connector.h>
#include <drm/drm_managed.h>
#include <drm/drm_of.h>
-#include <drm/drm_panel.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_simple_kms_helper.h>
+#include <drm/bridge/imx.h>
#include "imx-drm.h"
struct imx_parallel_display_encoder {
- struct drm_connector connector;
struct drm_encoder encoder;
struct drm_bridge bridge;
struct imx_parallel_display *pd;
@@ -34,79 +31,15 @@ struct imx_parallel_display_encoder {
struct imx_parallel_display {
struct device *dev;
- const struct drm_edid *drm_edid;
u32 bus_format;
- u32 bus_flags;
- struct drm_display_mode mode;
- struct drm_panel *panel;
struct drm_bridge *next_bridge;
};
-static inline struct imx_parallel_display *con_to_imxpd(struct drm_connector *c)
-{
- return container_of(c, struct imx_parallel_display_encoder, connector)->pd;
-}
-
static inline struct imx_parallel_display *bridge_to_imxpd(struct drm_bridge *b)
{
return container_of(b, struct imx_parallel_display_encoder, bridge)->pd;
}
-static int imx_pd_connector_get_modes(struct drm_connector *connector)
-{
- struct imx_parallel_display *imxpd = con_to_imxpd(connector);
- struct device_node *np = imxpd->dev->of_node;
- int num_modes;
-
- num_modes = drm_panel_get_modes(imxpd->panel, connector);
- if (num_modes > 0)
- return num_modes;
-
- if (imxpd->drm_edid) {
- drm_edid_connector_update(connector, imxpd->drm_edid);
- num_modes = drm_edid_connector_add_modes(connector);
- }
-
- if (np) {
- struct drm_display_mode *mode = drm_mode_create(connector->dev);
- int ret;
-
- if (!mode)
- return 0;
-
- ret = of_get_drm_display_mode(np, &imxpd->mode,
- &imxpd->bus_flags,
- OF_USE_NATIVE_MODE);
- if (ret) {
- drm_mode_destroy(connector->dev, mode);
- return 0;
- }
-
- drm_mode_copy(mode, &imxpd->mode);
- mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
- drm_mode_probed_add(connector, mode);
- num_modes++;
- }
-
- return num_modes;
-}
-
-static void imx_pd_bridge_enable(struct drm_bridge *bridge)
-{
- struct imx_parallel_display *imxpd = bridge_to_imxpd(bridge);
-
- drm_panel_prepare(imxpd->panel);
- drm_panel_enable(imxpd->panel);
-}
-
-static void imx_pd_bridge_disable(struct drm_bridge *bridge)
-{
- struct imx_parallel_display *imxpd = bridge_to_imxpd(bridge);
-
- drm_panel_disable(imxpd->panel);
- drm_panel_unprepare(imxpd->panel);
-}
-
static const u32 imx_pd_bus_fmts[] = {
MEDIA_BUS_FMT_RGB888_1X24,
MEDIA_BUS_FMT_BGR888_1X24,
@@ -200,7 +133,6 @@ static int imx_pd_bridge_atomic_check(struct drm_bridge *bridge,
{
struct imx_crtc_state *imx_crtc_state = to_imx_crtc_state(crtc_state);
struct drm_display_info *di = &conn_state->connector->display_info;
- struct imx_parallel_display *imxpd = bridge_to_imxpd(bridge);
struct drm_bridge_state *next_bridge_state = NULL;
struct drm_bridge *next_bridge;
u32 bus_flags, bus_fmt;
@@ -212,10 +144,8 @@ static int imx_pd_bridge_atomic_check(struct drm_bridge *bridge,
if (next_bridge_state)
bus_flags = next_bridge_state->input_bus_cfg.flags;
- else if (di->num_bus_formats)
- bus_flags = di->bus_flags;
else
- bus_flags = imxpd->bus_flags;
+ bus_flags = di->bus_flags;
bus_fmt = bridge_state->input_bus_cfg.format;
if (!imx_pd_format_supported(bus_fmt))
@@ -231,21 +161,16 @@ static int imx_pd_bridge_atomic_check(struct drm_bridge *bridge,
return 0;
}
-static const struct drm_connector_funcs imx_pd_connector_funcs = {
- .fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = imx_drm_connector_destroy,
- .reset = drm_atomic_helper_connector_reset,
- .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
+static int imx_pd_bridge_attach(struct drm_bridge *bridge,
+ enum drm_bridge_attach_flags flags)
+{
+ struct imx_parallel_display *imxpd = bridge_to_imxpd(bridge);
-static const struct drm_connector_helper_funcs imx_pd_connector_helper_funcs = {
- .get_modes = imx_pd_connector_get_modes,
-};
+ return drm_bridge_attach(bridge->encoder, imxpd->next_bridge, bridge, flags);
+}
static const struct drm_bridge_funcs imx_pd_bridge_funcs = {
- .enable = imx_pd_bridge_enable,
- .disable = imx_pd_bridge_disable,
+ .attach = imx_pd_bridge_attach,
.atomic_reset = drm_atomic_helper_bridge_reset,
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
@@ -270,7 +195,6 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
return PTR_ERR(imxpd_encoder);
imxpd_encoder->pd = imxpd;
- connector = &imxpd_encoder->connector;
encoder = &imxpd_encoder->encoder;
bridge = &imxpd_encoder->bridge;
@@ -278,28 +202,14 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
if (ret)
return ret;
- /* set the connector's dpms to OFF so that
- * drm_helper_connector_dpms() won't return
- * immediately since the current state is ON
- * at this point.
- */
- connector->dpms = DRM_MODE_DPMS_OFF;
-
bridge->funcs = &imx_pd_bridge_funcs;
- drm_bridge_attach(encoder, bridge, NULL, 0);
-
- if (imxpd->next_bridge) {
- ret = drm_bridge_attach(encoder, imxpd->next_bridge, bridge, 0);
- if (ret < 0)
- return ret;
- } else {
- drm_connector_helper_add(connector,
- &imx_pd_connector_helper_funcs);
- drm_connector_init(drm, connector, &imx_pd_connector_funcs,
- DRM_MODE_CONNECTOR_DPI);
-
- drm_connector_attach_encoder(connector, encoder);
- }
+ drm_bridge_attach(encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+
+ connector = drm_bridge_connector_init(drm, encoder);
+ if (IS_ERR(connector))
+ return PTR_ERR(connector);
+
+ drm_connector_attach_encoder(connector, encoder);
return 0;
}
@@ -312,9 +222,7 @@ static int imx_pd_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
- const u8 *edidp;
struct imx_parallel_display *imxpd;
- int edid_len;
int ret;
u32 bus_format = 0;
const char *fmt;
@@ -324,14 +232,13 @@ static int imx_pd_probe(struct platform_device *pdev)
return -ENOMEM;
/* port@1 is the output port */
- ret = drm_of_find_panel_or_bridge(np, 1, 0, &imxpd->panel,
- &imxpd->next_bridge);
- if (ret && ret != -ENODEV)
+ imxpd->next_bridge = devm_drm_of_get_bridge(dev, np, 1, 0);
+ if (imxpd->next_bridge == ERR_PTR(-ENODEV))
+ imxpd->next_bridge = devm_imx_drm_legacy_bridge(dev, np, DRM_MODE_CONNECTOR_DPI);
+ if (IS_ERR(imxpd->next_bridge)) {
+ ret = PTR_ERR(imxpd->next_bridge);
return ret;
-
- edidp = of_get_property(np, "edid", &edid_len);
- if (edidp)
- imxpd->drm_edid = drm_edid_alloc(edidp, edid_len);
+ }
ret = of_property_read_string(np, "interface-pix-fmt", &fmt);
if (!ret) {
@@ -355,11 +262,7 @@ static int imx_pd_probe(struct platform_device *pdev)
static void imx_pd_remove(struct platform_device *pdev)
{
- struct imx_parallel_display *imxpd = platform_get_drvdata(pdev);
-
component_del(&pdev->dev, &imx_pd_ops);
-
- drm_edid_free(imxpd->drm_edid);
}
static const struct of_device_id imx_pd_dt_ids[] = {
diff --git a/drivers/gpu/drm/imx/lcdc/Kconfig b/drivers/gpu/drm/imx/lcdc/Kconfig
index 9c28bb0f4662f..75869489b0e61 100644
--- a/drivers/gpu/drm/imx/lcdc/Kconfig
+++ b/drivers/gpu/drm/imx/lcdc/Kconfig
@@ -1,6 +1,7 @@
config DRM_IMX_LCDC
tristate "Freescale i.MX LCDC displays"
depends on DRM && (ARCH_MXC || COMPILE_TEST)
+ select DRM_CLIENT_SELECTION
select DRM_GEM_DMA_HELPER
select DRM_KMS_HELPER
select DRM_DISPLAY_HELPER
diff --git a/drivers/gpu/drm/imx/lcdc/imx-lcdc.c b/drivers/gpu/drm/imx/lcdc/imx-lcdc.c
index 36668455aee8c..3215c4acd6753 100644
--- a/drivers/gpu/drm/imx/lcdc/imx-lcdc.c
+++ b/drivers/gpu/drm/imx/lcdc/imx-lcdc.c
@@ -3,6 +3,7 @@
#include <drm/drm_bridge.h>
#include <drm/drm_bridge_connector.h>
+#include <drm/drm_client_setup.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_fbdev_dma.h>
@@ -348,6 +349,7 @@ static struct drm_driver imx_lcdc_drm_driver = {
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
.fops = &imx_lcdc_drm_fops,
DRM_GEM_DMA_DRIVER_OPS_VMAP,
+ DRM_FBDEV_DMA_DRIVER_OPS,
.name = "imx-lcdc",
.desc = "i.MX LCDC driver",
.date = "20200716",
@@ -501,7 +503,7 @@ static int imx_lcdc_probe(struct platform_device *pdev)
if (ret)
return dev_err_probe(dev, ret, "Cannot register device\n");
- drm_fbdev_dma_setup(drm, 0);
+ drm_client_setup(drm, NULL);
return 0;
}