Merge tag 'drm-misc-next-2026-01-08' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next

drm-misc-next for 6.20:

UAPI Changes:

Cross-subsystem Changes:

Core Changes:
  - draw: Add API to check if a format conversion can be done
  - panic: Rename draw_panic_static_* to draw_panic_screen_*, Add kunit
    tests
  - shmem: Improve tests

Driver Changes:
  - ast: Big endian fixes
  - etnaviv: Add PPU flop reset support
  - panfrost: Add GPU_PM_RT support for RZ/G3E SoC
  - panthor: multiple fixes around VM termination, huge page support
  - pl111: Fix build regression
  - v3d: Fix DMA segment size

  - bridge:
    - Add connector argument to .hpd_notify
    - Plenty of patches to convert existing drivers to refcounting
    - Convert Rockchip's inno hdmi support to a proper bridge
    - lontium-lt9611uxc: Switch to HDMI audio helpers

  - panel:
    - New panel: BOE NV140WUM-T08

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

From: Maxime Ripard <mripard@redhat.com>
Link: https://patch.msgid.link/20260108-literate-nyala-of-courtesy-de501a@houat
This commit is contained in:
Dave Airlie
2026-01-09 14:17:58 +10:00
61 changed files with 1590 additions and 716 deletions
+16
View File
@@ -506,6 +506,22 @@ Contact: Maxime Ripard <mripard@kernel.org>,
Level: Intermediate
Convert users of of_drm_find_bridge() to of_drm_find_and_get_bridge()
---------------------------------------------------------------------
Taking a struct drm_bridge pointer requires getting a reference and putting
it after disposing of the pointer. Most functions returning a struct
drm_bridge pointer already call drm_bridge_get() to increment the refcount
and their users have been updated to call drm_bridge_put() when
appropriate. of_drm_find_bridge() does not get a reference and it has been
deprecated in favor of of_drm_find_and_get_bridge() which does, but some
users still need to be converted.
Contact: Maxime Ripard <mripard@kernel.org>,
Luca Ceresoli <luca.ceresoli@bootlin.com>
Level: Intermediate
Core refactorings
=================
+9
View File
@@ -8749,6 +8749,7 @@ T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
F: drivers/gpu/drm/drm_draw.c
F: drivers/gpu/drm/drm_draw_internal.h
F: drivers/gpu/drm/drm_panic*.c
F: drivers/gpu/drm/tests/drm_panic_test.c
F: include/drm/drm_panic*
DRM PANIC QR CODE
@@ -12457,6 +12458,14 @@ M: Samuel Holland <samuel@sholland.org>
S: Maintained
F: drivers/power/supply/ip5xxx_power.c
INNOSILICON HDMI BRIDGE DRIVER
M: Andy Yan <andy.yan@rock-chips.com>
L: dri-devel@lists.freedesktop.org
S: Maintained
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
F: drivers/gpu/drm/bridge/inno-hdmi.c
F: include/drm/bridge/inno_hdmi.h
INOTIFY
M: Jan Kara <jack@suse.cz>
R: Amir Goldstein <amir73il@gmail.com>
@@ -23,6 +23,9 @@
* Authors: AMD
*
*/
#include <drm/drm_colorop.h>
#include "amdgpu.h"
#include "amdgpu_mode.h"
#include "amdgpu_dm.h"
+8 -3
View File
@@ -93,12 +93,17 @@ static void ast_set_cursor_image(struct ast_device *ast, const u8 *src,
unsigned int width, unsigned int height)
{
u8 __iomem *dst = ast_plane_vaddr(&ast->cursor_plane.base);
u32 csum;
csum = ast_cursor_calculate_checksum(src, width, height);
u32 csum = ast_cursor_calculate_checksum(src, width, height);
/* write pixel data */
#if defined(__BIG_ENDIAN)
unsigned int i;
for (i = 0; i < AST_HWC_SIZE; i += 2)
writew(swab16(*(const __u16 *)&src[i]), &dst[i]);
#else
memcpy_toio(dst, src, AST_HWC_SIZE);
#endif
/* write checksum + signature */
dst += AST_HWC_SIZE;
+9 -2
View File
@@ -526,12 +526,18 @@ static int ast_primary_plane_helper_atomic_check(struct drm_plane *plane,
static void ast_handle_damage(struct ast_plane *ast_plane, struct iosys_map *src,
struct drm_framebuffer *fb,
const struct drm_rect *clip)
const struct drm_rect *clip,
struct drm_format_conv_state *fmtcnv_state)
{
struct iosys_map dst = IOSYS_MAP_INIT_VADDR_IOMEM(ast_plane_vaddr(ast_plane));
iosys_map_incr(&dst, drm_fb_clip_offset(fb->pitches[0], fb->format, clip));
#if defined(__BIG_ENDIAN)
drm_fb_swab(&dst, fb->pitches, src, fb, clip, !src[0].is_iomem, fmtcnv_state);
#else
drm_fb_memcpy(&dst, fb->pitches, src, fb, clip);
#endif
}
static void ast_primary_plane_helper_atomic_update(struct drm_plane *plane,
@@ -561,7 +567,8 @@ static void ast_primary_plane_helper_atomic_update(struct drm_plane *plane,
if (drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE) == 0) {
drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
ast_handle_damage(ast_plane, shadow_plane_state->data, fb, &damage);
ast_handle_damage(ast_plane, shadow_plane_state->data, fb, &damage,
&shadow_plane_state->fmtcnv_state);
}
drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
+7
View File
@@ -100,6 +100,13 @@ config DRM_I2C_NXP_TDA998X
help
Support for NXP Semiconductors TDA998X HDMI encoders.
config DRM_INNO_HDMI
tristate
select DRM_BRIDGE_CONNECTOR
select DRM_DISPLAY_HDMI_HELPER
select DRM_DISPLAY_HELPER
select DRM_KMS_HELPER
config DRM_ITE_IT6263
tristate "ITE IT6263 LVDS/HDMI bridge"
depends on OF
+1
View File
@@ -10,6 +10,7 @@ obj-$(CONFIG_DRM_FSL_LDB) += fsl-ldb.o
tda998x-y := tda998x_drv.o
obj-$(CONFIG_DRM_I2C_NXP_TDA998X) += tda998x.o
obj-$(CONFIG_DRM_INNO_HDMI) += inno-hdmi.o
obj-$(CONFIG_DRM_ITE_IT6263) += ite-it6263.o
obj-$(CONFIG_DRM_ITE_IT6505) += ite-it6505.o
obj-$(CONFIG_DRM_LONTIUM_LT8912B) += lontium-lt8912b.o
@@ -60,7 +60,6 @@ enum imx8qxp_pc_pix_data_format {
struct imx8qxp_pc_channel {
struct drm_bridge bridge;
struct drm_bridge *next_bridge;
struct imx8qxp_pc *pc;
unsigned int stream_id;
};
@@ -120,7 +119,7 @@ static int imx8qxp_pc_bridge_attach(struct drm_bridge *bridge,
}
return drm_bridge_attach(encoder,
ch->next_bridge, bridge,
ch->bridge.next_bridge, bridge,
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
}
@@ -326,8 +325,8 @@ static int imx8qxp_pc_bridge_probe(struct platform_device *pdev)
goto free_child;
}
ch->next_bridge = of_drm_find_bridge(remote);
if (!ch->next_bridge) {
ch->bridge.next_bridge = of_drm_find_and_get_bridge(remote);
if (!ch->bridge.next_bridge) {
of_node_put(remote);
ret = -EPROBE_DEFER;
DRM_DEV_DEBUG_DRIVER(dev,
@@ -349,7 +348,7 @@ static int imx8qxp_pc_bridge_probe(struct platform_device *pdev)
free_child:
of_node_put(child);
if (i == 1 && pc->ch[0]->next_bridge)
if (i == 1 && pc->ch[0]->bridge.next_bridge)
drm_bridge_remove(&pc->ch[0]->bridge);
pm_runtime_disable(dev);
@@ -374,13 +374,8 @@ static int imx8qxp_pixel_link_bridge_probe(struct platform_device *pdev)
return ret;
pl->next_bridge = imx8qxp_pixel_link_find_next_bridge(pl);
if (IS_ERR(pl->next_bridge)) {
ret = PTR_ERR(pl->next_bridge);
if (ret != -EPROBE_DEFER)
DRM_DEV_ERROR(dev, "failed to find next bridge: %d\n",
ret);
return ret;
}
if (IS_ERR(pl->next_bridge))
return PTR_ERR(pl->next_bridge);
platform_set_drvdata(pdev, pl);
+26 -37
View File
@@ -35,7 +35,6 @@
struct imx8qxp_pxl2dpi {
struct regmap *regmap;
struct drm_bridge bridge;
struct drm_bridge *next_bridge;
struct drm_bridge *companion;
struct device *dev;
struct imx_sc_ipc *ipc_handle;
@@ -60,10 +59,17 @@ static int imx8qxp_pxl2dpi_bridge_attach(struct drm_bridge *bridge,
}
return drm_bridge_attach(encoder,
p2d->next_bridge, bridge,
p2d->bridge.next_bridge, bridge,
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
}
static void imx8qxp_pxl2dpi_bridge_destroy(struct drm_bridge *bridge)
{
struct imx8qxp_pxl2dpi *p2d = bridge->driver_private;
drm_bridge_put(p2d->companion);
}
static int
imx8qxp_pxl2dpi_bridge_atomic_check(struct drm_bridge *bridge,
struct drm_bridge_state *bridge_state,
@@ -206,6 +212,7 @@ static const struct drm_bridge_funcs imx8qxp_pxl2dpi_bridge_funcs = {
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
.atomic_reset = drm_atomic_helper_bridge_reset,
.attach = imx8qxp_pxl2dpi_bridge_attach,
.destroy = imx8qxp_pxl2dpi_bridge_destroy,
.atomic_check = imx8qxp_pxl2dpi_bridge_atomic_check,
.mode_set = imx8qxp_pxl2dpi_bridge_mode_set,
.atomic_disable = imx8qxp_pxl2dpi_bridge_atomic_disable,
@@ -255,40 +262,27 @@ out:
return ep;
}
static struct drm_bridge *
imx8qxp_pxl2dpi_find_next_bridge(struct imx8qxp_pxl2dpi *p2d)
static int imx8qxp_pxl2dpi_find_next_bridge(struct imx8qxp_pxl2dpi *p2d)
{
struct device_node *ep, *remote;
struct drm_bridge *next_bridge;
int ret;
struct device_node *ep __free(device_node) =
imx8qxp_pxl2dpi_get_available_ep_from_port(p2d, 1);
if (IS_ERR(ep))
return PTR_ERR(ep);
ep = imx8qxp_pxl2dpi_get_available_ep_from_port(p2d, 1);
if (IS_ERR(ep)) {
ret = PTR_ERR(ep);
return ERR_PTR(ret);
}
remote = of_graph_get_remote_port_parent(ep);
struct device_node *remote __free(device_node) = of_graph_get_remote_port_parent(ep);
if (!remote || !of_device_is_available(remote)) {
DRM_DEV_ERROR(p2d->dev, "no available remote\n");
next_bridge = ERR_PTR(-ENODEV);
goto out;
return -ENODEV;
} else if (!of_device_is_available(remote->parent)) {
DRM_DEV_ERROR(p2d->dev, "remote parent is not available\n");
next_bridge = ERR_PTR(-ENODEV);
goto out;
return -ENODEV;
}
next_bridge = of_drm_find_bridge(remote);
if (!next_bridge) {
next_bridge = ERR_PTR(-EPROBE_DEFER);
goto out;
}
out:
of_node_put(remote);
of_node_put(ep);
p2d->bridge.next_bridge = of_drm_find_and_get_bridge(remote);
if (!p2d->bridge.next_bridge)
return -EPROBE_DEFER;
return next_bridge;
return 0;
}
static int imx8qxp_pxl2dpi_set_pixel_link_sel(struct imx8qxp_pxl2dpi *p2d)
@@ -347,7 +341,7 @@ static int imx8qxp_pxl2dpi_parse_dt_companion(struct imx8qxp_pxl2dpi *p2d)
goto out;
}
p2d->companion = of_drm_find_bridge(companion);
p2d->companion = of_drm_find_and_get_bridge(companion);
if (!p2d->companion) {
ret = -EPROBE_DEFER;
DRM_DEV_DEBUG_DRIVER(p2d->dev,
@@ -364,8 +358,8 @@ static int imx8qxp_pxl2dpi_parse_dt_companion(struct imx8qxp_pxl2dpi *p2d)
* the next bridges are connected to. If they are marked as expecting
* even pixels and odd pixels than we need to use the companion PXL2DPI.
*/
port1 = of_graph_get_port_by_id(p2d->next_bridge->of_node, 1);
port2 = of_graph_get_port_by_id(companion_p2d->next_bridge->of_node, 1);
port1 = of_graph_get_port_by_id(p2d->bridge.next_bridge->of_node, 1);
port2 = of_graph_get_port_by_id(companion_p2d->bridge.next_bridge->of_node, 1);
dual_link = drm_of_lvds_get_dual_link_pixel_order(port1, port2);
of_node_put(port1);
of_node_put(port2);
@@ -421,14 +415,9 @@ static int imx8qxp_pxl2dpi_bridge_probe(struct platform_device *pdev)
return ret;
}
p2d->next_bridge = imx8qxp_pxl2dpi_find_next_bridge(p2d);
if (IS_ERR(p2d->next_bridge)) {
ret = PTR_ERR(p2d->next_bridge);
if (ret != -EPROBE_DEFER)
DRM_DEV_ERROR(dev, "failed to find next bridge: %d\n",
ret);
ret = imx8qxp_pxl2dpi_find_next_bridge(p2d);
if (ret)
return ret;
}
ret = imx8qxp_pxl2dpi_set_pixel_link_sel(p2d);
if (ret)
File diff suppressed because it is too large Load Diff
+3 -4
View File
@@ -298,7 +298,6 @@ struct it66121_chip_info {
struct it66121_ctx {
struct regmap *regmap;
struct drm_bridge bridge;
struct drm_bridge *next_bridge;
struct drm_connector *connector;
struct device *dev;
struct gpio_desc *gpio_reset;
@@ -596,7 +595,7 @@ static int it66121_bridge_attach(struct drm_bridge *bridge,
if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
return -EINVAL;
ret = drm_bridge_attach(encoder, ctx->next_bridge, bridge, flags);
ret = drm_bridge_attach(encoder, ctx->bridge.next_bridge, bridge, flags);
if (ret)
return ret;
@@ -1543,9 +1542,9 @@ static int it66121_probe(struct i2c_client *client)
return -EINVAL;
}
ctx->next_bridge = of_drm_find_bridge(ep);
ctx->bridge.next_bridge = of_drm_find_and_get_bridge(ep);
of_node_put(ep);
if (!ctx->next_bridge) {
if (!ctx->bridge.next_bridge) {
dev_dbg(ctx->dev, "Next bridge not found, deferring probe\n");
return -EPROBE_DEFER;
}
+49 -76
View File
@@ -17,8 +17,6 @@
#include <linux/wait.h>
#include <linux/workqueue.h>
#include <sound/hdmi-codec.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_edid.h>
@@ -27,6 +25,8 @@
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
#include <drm/display/drm_hdmi_audio_helper.h>
#define EDID_BLOCK_SIZE 128
#define EDID_NUM_BLOCKS 2
@@ -48,7 +48,6 @@ struct lt9611uxc {
struct device_node *dsi1_node;
struct mipi_dsi_device *dsi0;
struct mipi_dsi_device *dsi1;
struct platform_device *audio_pdev;
struct gpio_desc *reset_gpio;
struct gpio_desc *enable_gpio;
@@ -429,12 +428,52 @@ static const struct drm_edid *lt9611uxc_bridge_edid_read(struct drm_bridge *brid
return drm_edid_read_custom(connector, lt9611uxc_get_edid_block, lt9611uxc);
}
static void lt9611uxc_bridge_hpd_notify(struct drm_bridge *bridge,
struct drm_connector *connector,
enum drm_connector_status status)
{
const struct drm_edid *drm_edid;
if (status == connector_status_disconnected) {
drm_connector_hdmi_audio_plugged_notify(connector, false);
drm_edid_connector_update(connector, NULL);
return;
}
drm_edid = lt9611uxc_bridge_edid_read(bridge, connector);
drm_edid_connector_update(connector, drm_edid);
drm_edid_free(drm_edid);
if (status == connector_status_connected)
drm_connector_hdmi_audio_plugged_notify(connector, true);
}
static int lt9611uxc_hdmi_audio_prepare(struct drm_bridge *bridge,
struct drm_connector *connector,
struct hdmi_codec_daifmt *fmt,
struct hdmi_codec_params *hparms)
{
/*
* LT9611UXC will automatically detect rate and sample size, so no need
* to setup anything here.
*/
return 0;
}
static void lt9611uxc_hdmi_audio_shutdown(struct drm_bridge *bridge,
struct drm_connector *connector)
{
}
static const struct drm_bridge_funcs lt9611uxc_bridge_funcs = {
.attach = lt9611uxc_bridge_attach,
.mode_valid = lt9611uxc_bridge_mode_valid,
.mode_set = lt9611uxc_bridge_mode_set,
.detect = lt9611uxc_bridge_detect,
.edid_read = lt9611uxc_bridge_edid_read,
.hpd_notify = lt9611uxc_bridge_hpd_notify,
.hdmi_audio_prepare = lt9611uxc_hdmi_audio_prepare,
.hdmi_audio_shutdown = lt9611uxc_hdmi_audio_shutdown,
};
static int lt9611uxc_parse_dt(struct device *dev,
@@ -508,73 +547,6 @@ static int lt9611uxc_read_version(struct lt9611uxc *lt9611uxc)
return ret < 0 ? ret : rev;
}
static int lt9611uxc_hdmi_hw_params(struct device *dev, void *data,
struct hdmi_codec_daifmt *fmt,
struct hdmi_codec_params *hparms)
{
/*
* LT9611UXC will automatically detect rate and sample size, so no need
* to setup anything here.
*/
return 0;
}
static void lt9611uxc_audio_shutdown(struct device *dev, void *data)
{
}
static int lt9611uxc_hdmi_i2s_get_dai_id(struct snd_soc_component *component,
struct device_node *endpoint,
void *data)
{
struct of_endpoint of_ep;
int ret;
ret = of_graph_parse_endpoint(endpoint, &of_ep);
if (ret < 0)
return ret;
/*
* HDMI sound should be located as reg = <2>
* Then, it is sound port 0
*/
if (of_ep.port == 2)
return 0;
return -EINVAL;
}
static const struct hdmi_codec_ops lt9611uxc_codec_ops = {
.hw_params = lt9611uxc_hdmi_hw_params,
.audio_shutdown = lt9611uxc_audio_shutdown,
.get_dai_id = lt9611uxc_hdmi_i2s_get_dai_id,
};
static int lt9611uxc_audio_init(struct device *dev, struct lt9611uxc *lt9611uxc)
{
struct hdmi_codec_pdata codec_data = {
.ops = &lt9611uxc_codec_ops,
.max_i2s_channels = 2,
.i2s = 1,
.data = lt9611uxc,
};
lt9611uxc->audio_pdev =
platform_device_register_data(dev, HDMI_CODEC_DRV_NAME,
PLATFORM_DEVID_AUTO,
&codec_data, sizeof(codec_data));
return PTR_ERR_OR_ZERO(lt9611uxc->audio_pdev);
}
static void lt9611uxc_audio_exit(struct lt9611uxc *lt9611uxc)
{
if (lt9611uxc->audio_pdev) {
platform_device_unregister(lt9611uxc->audio_pdev);
lt9611uxc->audio_pdev = NULL;
}
}
#define LT9611UXC_FW_PAGE_SIZE 32
static void lt9611uxc_firmware_write_page(struct lt9611uxc *lt9611uxc, u16 addr, const u8 *buf)
{
@@ -858,11 +830,17 @@ retry:
i2c_set_clientdata(client, lt9611uxc);
lt9611uxc->bridge.of_node = client->dev.of_node;
lt9611uxc->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID;
lt9611uxc->bridge.ops = DRM_BRIDGE_OP_DETECT |
DRM_BRIDGE_OP_EDID |
DRM_BRIDGE_OP_HDMI_AUDIO;
if (lt9611uxc->hpd_supported)
lt9611uxc->bridge.ops |= DRM_BRIDGE_OP_HPD;
lt9611uxc->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
lt9611uxc->bridge.hdmi_audio_dev = dev;
lt9611uxc->bridge.hdmi_audio_max_i2s_playback_channels = 2;
lt9611uxc->bridge.hdmi_audio_dai_port = 2;
drm_bridge_add(&lt9611uxc->bridge);
/* Attach primary DSI */
@@ -881,10 +859,6 @@ retry:
}
}
ret = lt9611uxc_audio_init(dev, lt9611uxc);
if (ret)
goto err_remove_bridge;
return 0;
err_remove_bridge:
@@ -908,7 +882,6 @@ static void lt9611uxc_remove(struct i2c_client *client)
free_irq(client->irq, lt9611uxc);
cancel_work_sync(&lt9611uxc->work);
lt9611uxc_audio_exit(lt9611uxc);
drm_bridge_remove(&lt9611uxc->bridge);
mutex_destroy(&lt9611uxc->ocm_lock);
+7 -8
View File
@@ -31,7 +31,6 @@ struct simple_bridge {
const struct simple_bridge_info *info;
struct drm_bridge *next_bridge;
struct regulator *vdd;
struct gpio_desc *enable;
};
@@ -54,8 +53,8 @@ static int simple_bridge_get_modes(struct drm_connector *connector)
const struct drm_edid *drm_edid;
int ret;
if (sbridge->next_bridge->ops & DRM_BRIDGE_OP_EDID) {
drm_edid = drm_bridge_edid_read(sbridge->next_bridge, connector);
if (sbridge->bridge.next_bridge->ops & DRM_BRIDGE_OP_EDID) {
drm_edid = drm_bridge_edid_read(sbridge->bridge.next_bridge, connector);
if (!drm_edid)
DRM_INFO("EDID read failed. Fallback to standard modes\n");
} else {
@@ -90,7 +89,7 @@ simple_bridge_connector_detect(struct drm_connector *connector, bool force)
{
struct simple_bridge *sbridge = drm_connector_to_simple_bridge(connector);
return drm_bridge_detect(sbridge->next_bridge, connector);
return drm_bridge_detect(sbridge->bridge.next_bridge, connector);
}
static const struct drm_connector_funcs simple_bridge_con_funcs = {
@@ -109,7 +108,7 @@ static int simple_bridge_attach(struct drm_bridge *bridge,
struct simple_bridge *sbridge = drm_bridge_to_simple_bridge(bridge);
int ret;
ret = drm_bridge_attach(encoder, sbridge->next_bridge, bridge,
ret = drm_bridge_attach(encoder, sbridge->bridge.next_bridge, bridge,
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
if (ret < 0)
return ret;
@@ -122,7 +121,7 @@ static int simple_bridge_attach(struct drm_bridge *bridge,
ret = drm_connector_init_with_ddc(bridge->dev, &sbridge->connector,
&simple_bridge_con_funcs,
sbridge->info->connector_type,
sbridge->next_bridge->ddc);
sbridge->bridge.next_bridge->ddc);
if (ret) {
DRM_ERROR("Failed to initialize connector\n");
return ret;
@@ -180,10 +179,10 @@ static int simple_bridge_probe(struct platform_device *pdev)
if (!remote)
return -EINVAL;
sbridge->next_bridge = of_drm_find_bridge(remote);
sbridge->bridge.next_bridge = of_drm_find_and_get_bridge(remote);
of_node_put(remote);
if (!sbridge->next_bridge) {
if (!sbridge->bridge.next_bridge) {
dev_dbg(&pdev->dev, "Next bridge not found, deferring probe\n");
return -EPROBE_DEFER;
}
+1 -1
View File
@@ -182,7 +182,7 @@ static u32 drm_log_find_usable_format(struct drm_plane *plane)
int i;
for (i = 0; i < plane->format_count; i++)
if (drm_draw_color_from_xrgb8888(0xffffff, plane->format_types[i]) != 0)
if (drm_draw_can_convert_from_xrgb8888(plane->format_types[i]))
return plane->format_types[i];
return DRM_FORMAT_INVALID;
}
@@ -141,7 +141,7 @@ static void drm_bridge_connector_hpd_notify(struct drm_connector *connector,
/* Notify all bridges in the pipeline of hotplug events. */
drm_for_each_bridge_in_chain_scoped(bridge_connector->encoder, bridge) {
if (bridge->funcs->hpd_notify)
bridge->funcs->hpd_notify(bridge, status);
bridge->funcs->hpd_notify(bridge, connector, status);
}
}
+32
View File
@@ -641,6 +641,38 @@ drm_atomic_get_colorop_state(struct drm_atomic_state *state,
}
EXPORT_SYMBOL(drm_atomic_get_colorop_state);
/**
* drm_atomic_get_old_colorop_state - get colorop state, if it exists
* @state: global atomic state object
* @colorop: colorop to grab
*
* This function returns the old colorop state for the given colorop, or
* NULL if the colorop is not part of the global atomic state.
*/
struct drm_colorop_state *
drm_atomic_get_old_colorop_state(struct drm_atomic_state *state,
struct drm_colorop *colorop)
{
return state->colorops[drm_colorop_index(colorop)].old_state;
}
EXPORT_SYMBOL(drm_atomic_get_old_colorop_state);
/**
* drm_atomic_get_new_colorop_state - get colorop state, if it exists
* @state: global atomic state object
* @colorop: colorop to grab
*
* This function returns the new colorop state for the given colorop, or
* NULL if the colorop is not part of the global atomic state.
*/
struct drm_colorop_state *
drm_atomic_get_new_colorop_state(struct drm_atomic_state *state,
struct drm_colorop *colorop)
{
return state->colorops[drm_colorop_index(colorop)].new_state;
}
EXPORT_SYMBOL(drm_atomic_get_new_colorop_state);
static bool
plane_switching_crtc(const struct drm_plane_state *old_plane_state,
const struct drm_plane_state *new_plane_state)
+1
View File
@@ -34,6 +34,7 @@
#include <drm/drm_atomic_uapi.h>
#include <drm/drm_blend.h>
#include <drm/drm_bridge.h>
#include <drm/drm_colorop.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_device.h>
#include <drm/drm_drv.h>
+54 -15
View File
@@ -275,6 +275,8 @@ static void __drm_bridge_free(struct kref *kref)
if (bridge->funcs->destroy)
bridge->funcs->destroy(bridge);
drm_bridge_put(bridge->next_bridge);
kfree(bridge->container);
}
@@ -361,7 +363,7 @@ EXPORT_SYMBOL(__devm_drm_bridge_alloc);
* @bridge: bridge control structure
*
* Add the given bridge to the global list of bridges, where they can be
* found by users via of_drm_find_bridge().
* found by users via of_drm_find_and_get_bridge().
*
* The bridge to be added must have been allocated by
* devm_drm_bridge_alloc().
@@ -422,9 +424,9 @@ EXPORT_SYMBOL(devm_drm_bridge_add);
* @bridge: bridge control structure
*
* Remove the given bridge from the global list of registered bridges, so
* it won't be found by users via of_drm_find_bridge(), and add it to the
* lingering bridge list, to keep track of it until its allocated memory is
* eventually freed.
* it won't be found by users via of_drm_find_and_get_bridge(), and add it
* to the lingering bridge list, to keep track of it until its allocated
* memory is eventually freed.
*/
void drm_bridge_remove(struct drm_bridge *bridge)
{
@@ -1479,30 +1481,67 @@ void drm_bridge_hpd_notify(struct drm_bridge *bridge,
EXPORT_SYMBOL_GPL(drm_bridge_hpd_notify);
#ifdef CONFIG_OF
/**
* of_drm_find_and_get_bridge - find the bridge corresponding to the device
* node in the global bridge list
* @np: device node
*
* The refcount of the returned bridge is incremented. Use drm_bridge_put()
* when done with it.
*
* RETURNS:
* drm_bridge control struct on success, NULL on failure
*/
struct drm_bridge *of_drm_find_and_get_bridge(struct device_node *np)
{
struct drm_bridge *bridge;
scoped_guard(mutex, &bridge_lock) {
list_for_each_entry(bridge, &bridge_list, list)
if (bridge->of_node == np)
return drm_bridge_get(bridge);
}
return NULL;
}
EXPORT_SYMBOL(of_drm_find_and_get_bridge);
/**
* of_drm_find_bridge - find the bridge corresponding to the device node in
* the global bridge list
*
* @np: device node
*
* This function is deprecated. Convert to of_drm_find_and_get_bridge()
* instead for proper refcounting.
*
* The bridge returned by this function is not refcounted. This is
* dangerous because the bridge might be deallocated even before the caller
* has a chance to use it. To use this function you have to do one of:
* - get a reference with drm_bridge_get() as soon as possible to
* minimize the race window, and then drm_bridge_put() when no longer
* using the pointer
* - not call drm_bridge_get() or drm_bridge_put() at all, which used to
* be the correct practice before dynamic bridge lifetime was introduced
* - again, convert to of_drm_find_and_get_bridge(), which is the only safe
* thing to do
*
* RETURNS:
* drm_bridge control struct on success, NULL on failure
*/
struct drm_bridge *of_drm_find_bridge(struct device_node *np)
{
struct drm_bridge *bridge;
struct drm_bridge *bridge = of_drm_find_and_get_bridge(np);
mutex_lock(&bridge_lock);
/*
* We need to emulate the original semantics of
* of_drm_find_bridge(), which was not getting any bridge
* reference. Being now based on of_drm_find_and_get_bridge() which
* gets a reference, put it before returning.
*/
drm_bridge_put(bridge);
list_for_each_entry(bridge, &bridge_list, list) {
if (bridge->of_node == np) {
mutex_unlock(&bridge_lock);
return bridge;
}
}
mutex_unlock(&bridge_lock);
return NULL;
return bridge;
}
EXPORT_SYMBOL(of_drm_find_bridge);
#endif
+29
View File
@@ -15,6 +15,35 @@
#include "drm_draw_internal.h"
#include "drm_format_internal.h"
/**
* drm_draw_can_convert_from_xrgb8888 - check if xrgb8888 can be converted to the desired format
* @format: format
*
* Returns:
* True if XRGB8888 can be converted to the specified format, false otherwise.
*/
bool drm_draw_can_convert_from_xrgb8888(u32 format)
{
switch (format) {
case DRM_FORMAT_RGB565:
case DRM_FORMAT_RGBA5551:
case DRM_FORMAT_XRGB1555:
case DRM_FORMAT_ARGB1555:
case DRM_FORMAT_RGB888:
case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_ARGB8888:
case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_ABGR8888:
case DRM_FORMAT_XRGB2101010:
case DRM_FORMAT_ARGB2101010:
case DRM_FORMAT_ABGR2101010:
return true;
default:
return false;
}
}
EXPORT_SYMBOL(drm_draw_can_convert_from_xrgb8888);
/**
* drm_draw_color_from_xrgb8888 - convert one pixel from xrgb8888 to the desired format
* @color: input color, in xrgb8888 format

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