mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
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:
@@ -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
|
||||
=================
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 = <9611uxc_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(<9611uxc->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(<9611uxc->work);
|
||||
lt9611uxc_audio_exit(lt9611uxc);
|
||||
drm_bridge_remove(<9611uxc->bridge);
|
||||
|
||||
mutex_destroy(<9611uxc->ocm_lock);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user