summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2026-09-11 18:45:13 +1000
committerDave Airlie <airlied@redhat.com>2026-09-11 18:45:19 +1000
commit14d6074f52d3af2b27565e6957b92dceeb8b00da (patch)
tree507929b200eb41c10c133839fd366a75f30cbfb1
parentf5c6fdfa1f4460c5714cd4996c6aa280d25399ca (diff)
parent75ee88dae80d8c1141ef850bda9a26dbd1fe3c21 (diff)
Merge tag 'drm-misc-next-2026-09-10' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next
drm-misc-next for v7.4: Cross-subsystem Changes: firmware: - sysfb: Remove obsolete quirk for Lenovo D330 sound: - ti/omap: Fix build error Core Changes: edid: - support detecting panel size from EDID Driver Changes: amd: - display: Drop obsolete KUnit tests bridge: - analogix: Support eDP lane mapping - ti-sn65dsi83: Support LVDS Channel B on SN65DSI84 - minor cleanups gma500: - avoid unsupported ARGB formats in primary plane hibmc: - handle vblank interrupts correctly sysfb: - fix panel orientation for non-native display modes Signed-off-by: Dave Airlie <airlied@redhat.com> From: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patch.msgid.link/20260910140343.GA404885@linux.fritz.box
-rw-r--r--Documentation/devicetree/bindings/display/bridge/analogix,dp.yaml19
-rw-r--r--Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml1
-rw-r--r--drivers/firmware/efi/sysfb_efi.c9
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.h3
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c73
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix_dp_core.c84
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix_dp_core.h4
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c15
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h4
-rw-r--r--drivers/gpu/drm/bridge/lontium-lt8713sx.c2
-rw-r--r--drivers/gpu/drm/bridge/lontium-lt9211.c2
-rw-r--r--drivers/gpu/drm/bridge/lontium-lt9611.c2
-rw-r--r--drivers/gpu/drm/bridge/lontium-lt9611uxc.c2
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c209
-rw-r--r--drivers/gpu/drm/bridge/ti-sn65dsi83.c34
-rw-r--r--drivers/gpu/drm/drm_edid.c47
-rw-r--r--drivers/gpu/drm/drm_gem.c14
-rw-r--r--drivers/gpu/drm/gma500/psb_intel_display.c34
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c16
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c5
-rw-r--r--drivers/gpu/drm/msm/msm_gem_shrinker.c22
-rw-r--r--drivers/gpu/drm/panthor/panthor_gem.c14
-rw-r--r--drivers/gpu/drm/panthor/panthor_mmu.c5
-rw-r--r--drivers/gpu/drm/panthor/panthor_mmu.h3
-rw-r--r--drivers/gpu/drm/sysfb/efidrm.c17
-rw-r--r--drivers/gpu/drm/sysfb/ofdrm.c18
-rw-r--r--drivers/gpu/drm/sysfb/vesadrm.c17
-rw-r--r--include/drm/display/drm_dp_helper.h6
-rw-r--r--include/drm/drm_edid.h2
-rw-r--r--include/drm/drm_gem.h3
-rw-r--r--sound/soc/ti/omap-hdmi.c1
31 files changed, 301 insertions, 386 deletions
diff --git a/Documentation/devicetree/bindings/display/bridge/analogix,dp.yaml b/Documentation/devicetree/bindings/display/bridge/analogix,dp.yaml
index 62f0521b0924..ecf206871cdd 100644
--- a/Documentation/devicetree/bindings/display/bridge/analogix,dp.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/analogix,dp.yaml
@@ -42,13 +42,22 @@ properties:
properties:
port@0:
$ref: /schemas/graph.yaml#/properties/port
- description:
- Input node to receive pixel data.
+ description: Input node to receive pixel data.
port@1:
- $ref: /schemas/graph.yaml#/properties/port
- description:
- Port node with one endpoint connected to a dp-connector node.
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+ description: Port node with one endpoint connected to sink device node.
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ unevaluatedProperties: false
+ properties:
+ data-lanes:
+ minItems: 1
+ maxItems: 4
+ items:
+ enum: [ 0, 1, 2, 3 ]
required:
- port@0
diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml
index 6548f157fd96..39dafe75a680 100644
--- a/Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml
@@ -160,6 +160,7 @@ examples:
reg = <1>;
edp_out_panel: endpoint {
+ data-lanes = <0 1>;
remote-endpoint = <&panel_in_edp>;
};
};
diff --git a/drivers/firmware/efi/sysfb_efi.c b/drivers/firmware/efi/sysfb_efi.c
index 685283bb7327..2338de73c62c 100644
--- a/drivers/firmware/efi/sysfb_efi.c
+++ b/drivers/firmware/efi/sysfb_efi.c
@@ -302,15 +302,6 @@ static const struct dmi_system_id efifb_dmi_swap_width_height[] __initconst = {
.callback = efifb_swap_width_height,
},
{
- /* Lenovo D330 with 800x1280 or 1200x1920 portrait screen */
- .matches = {
- DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_EXACT_MATCH(DMI_PRODUCT_VERSION,
- "Lenovo ideapad D330-10IGM"),
- },
- .callback = efifb_swap_width_height,
- },
- {
/*
* Lenovo IdeaPad Duet 3 10IGL5 and 10IGL5-LTE with
* 1200x1920 portrait screen
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.h
index 4e9eb3ff2c90..ce900844602e 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.h
@@ -153,9 +153,6 @@ void parse_edid_displayid_vrr(struct drm_connector *connector,
const struct edid *edid);
int get_amd_vsdb(struct amdgpu_dm_connector *aconnector,
struct amdgpu_hdmi_vsdb_info *vsdb_info);
-int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector,
- const struct edid *edid,
- struct amdgpu_hdmi_vsdb_info *vsdb_info);
void amdgpu_dm_connector_funcs_force(struct drm_connector *connector);
enum dc_status dm_validate_stream_and_context(struct dc *dc,
struct dc_stream_state *stream);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c
index 0d2f9dbce0a9..03038cc54cc0 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c
@@ -4875,75 +4875,6 @@ static void dm_test_get_amd_vsdb_supported(struct kunit *test)
}
/**
- * dm_test_parse_hdmi_amd_vsdb_null_edid - Test NULL EDID returns -ENODEV
- * @test: The KUnit test context
- */
-static void dm_test_parse_hdmi_amd_vsdb_null_edid(struct kunit *test)
-{
- struct amdgpu_dm_connector *aconnector;
- struct amdgpu_hdmi_vsdb_info vsdb_info = {0};
-
- aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
- KUNIT_ASSERT_NOT_NULL(test, aconnector);
-
- KUNIT_EXPECT_EQ(test,
- parse_hdmi_amd_vsdb(aconnector, NULL, &vsdb_info),
- -ENODEV);
-}
-
-/**
- * dm_test_parse_hdmi_amd_vsdb_no_extensions - Test EDID without extensions
- * @test: The KUnit test context
- *
- * An EDID that declares no extension blocks has no CEA block to parse.
- */
-static void dm_test_parse_hdmi_amd_vsdb_no_extensions(struct kunit *test)
-{
- struct amdgpu_dm_connector *aconnector;
- struct amdgpu_hdmi_vsdb_info vsdb_info = {0};
- struct edid *edid;
-
- aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
- KUNIT_ASSERT_NOT_NULL(test, aconnector);
- edid = kunit_kzalloc(test, sizeof(*edid), GFP_KERNEL);
- KUNIT_ASSERT_NOT_NULL(test, edid);
-
- edid->extensions = 0;
-
- KUNIT_EXPECT_EQ(test,
- parse_hdmi_amd_vsdb(aconnector, edid, &vsdb_info),
- -ENODEV);
-}
-
-/**
- * dm_test_parse_hdmi_amd_vsdb_no_cea_ext - Test EDID with no CEA extension
- * @test: The KUnit test context
- *
- * An extension block that is not a CEA block leaves no VSDB to parse.
- */
-static void dm_test_parse_hdmi_amd_vsdb_no_cea_ext(struct kunit *test)
-{
- struct amdgpu_dm_connector *aconnector;
- struct amdgpu_hdmi_vsdb_info vsdb_info = {0};
- struct edid *edid;
- u8 *raw;
-
- aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
- KUNIT_ASSERT_NOT_NULL(test, aconnector);
-
- /* Base block + one extension block that is NOT a CEA extension. */
- raw = kunit_kzalloc(test, 2 * EDID_LENGTH, GFP_KERNEL);
- KUNIT_ASSERT_NOT_NULL(test, raw);
- edid = (struct edid *)raw;
- edid->extensions = 1;
- raw[EDID_LENGTH] = DM_TEST_DISPLAYID_EXT;
-
- KUNIT_EXPECT_EQ(test,
- parse_hdmi_amd_vsdb(aconnector, edid, &vsdb_info),
- -ENODEV);
-}
-
-/**
* dm_test_parse_displayid_vrr_null_edid - Test NULL EDID leaves range untouched
* @test: The KUnit test context
*/
@@ -5647,10 +5578,6 @@ static struct kunit_case amdgpu_dm_connector_tests[] = {
/* get_amd_vsdb */
KUNIT_CASE(dm_test_get_amd_vsdb_unsupported),
KUNIT_CASE(dm_test_get_amd_vsdb_supported),
- /* parse_hdmi_amd_vsdb */
- KUNIT_CASE(dm_test_parse_hdmi_amd_vsdb_null_edid),
- KUNIT_CASE(dm_test_parse_hdmi_amd_vsdb_no_extensions),
- KUNIT_CASE(dm_test_parse_hdmi_amd_vsdb_no_cea_ext),
/* parse_edid_displayid_vrr */
KUNIT_CASE(dm_test_parse_displayid_vrr_null_edid),
KUNIT_CASE(dm_test_parse_displayid_vrr_no_displayid),
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 566f1e5eb8cd..18e76d1e78e1 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1244,10 +1244,78 @@ static const struct drm_bridge_funcs analogix_dp_bridge_funcs = {
.detect = analogix_dp_bridge_detect,
};
+static int analogix_dp_dt_parse_lanes_map(struct analogix_dp_device *dp)
+{
+ struct video_info *video_info = &dp->video_info;
+ struct device_node *endpoint;
+ u32 lane_idx[LANE_COUNT4];
+ u32 map[LANE_COUNT4] = {0, 1, 2, 3};
+ bool used[LANE_COUNT4] = {false};
+ int num_lanes;
+ int ret, i;
+
+ memcpy(video_info->lane_map, map, sizeof(map));
+
+ num_lanes = drm_of_get_data_lanes_count_ep(dp->dev->of_node, 1, 0, 1,
+ video_info->max_lane_count);
+ if (num_lanes < 0)
+ return -EINVAL;
+
+ endpoint = of_graph_get_endpoint_by_regs(dp->dev->of_node, 1, 0);
+ if (!endpoint)
+ return -EINVAL;
+
+ ret = of_property_read_u32_array(endpoint, "data-lanes", lane_idx, num_lanes);
+ of_node_put(endpoint);
+ if (ret)
+ return -EINVAL;
+
+ for (i = 0; i < num_lanes; i++) {
+ if (lane_idx[i] >= LANE_COUNT4) {
+ dev_dbg(dp->dev, "data-lanes[%d] = %u is out of range\n", i, lane_idx[i]);
+ return -EINVAL;
+ }
+
+ if (used[lane_idx[i]]) {
+ dev_dbg(dp->dev, "data-lanes[%d] = %u is duplicate\n", i, lane_idx[i]);
+ return -EINVAL;
+ }
+
+ used[lane_idx[i]] = true;
+ map[i] = lane_idx[i];
+ }
+
+ /*
+ * Fill the map[] entries not described by 'data-lanes' with the
+ * lane indices not used so far, e.g. for 'data-lanes = <3 1>':
+ *
+ * used[] = {0, 1, 0, 1} // only lanes 1 and 3 are used
+ * map[] before = {3, 1, x, x} // x = unassigned
+ * map[] after = {3, 1, 0, 2}
+ *
+ * Unused entries have no effect on the current link with fewer
+ * lanes in use, but filling them with distinct indices keeps the
+ * LANE_MAP register holding a valid permutation, just like its
+ * reset value (0xe4), so the mapping remains sane if a sink with
+ * a different lane count is connected later, e.g. via DP hot-plug.
+ */
+ for (i = 0; i < LANE_COUNT4 && num_lanes < LANE_COUNT4; i++) {
+ if (!used[i])
+ map[num_lanes++] = i;
+ }
+
+ dev_dbg(dp->dev, "Using parsed lane map: <%u %u %u %u>\n", map[0], map[1], map[2], map[3]);
+
+ memcpy(video_info->lane_map, map, sizeof(map));
+
+ return 0;
+}
+
static int analogix_dp_dt_parse_pdata(struct analogix_dp_device *dp)
{
struct device_node *dp_node = dp->dev->of_node;
struct video_info *video_info = &dp->video_info;
+ u32 val;
switch (dp->plat_data->dev_type) {
case RK3288_DP:
@@ -1269,13 +1337,21 @@ static int analogix_dp_dt_parse_pdata(struct analogix_dp_device *dp)
* NOTE: those property parseing code is used for
* providing backward compatibility for samsung platform.
*/
- of_property_read_u32(dp_node, "samsung,link-rate",
- &video_info->max_link_rate);
- of_property_read_u32(dp_node, "samsung,lane-count",
- &video_info->max_lane_count);
+ if (of_property_read_u32(dp_node, "samsung,link-rate", &val))
+ return dev_err_probe(dp->dev, -EINVAL,
+ "Failed to get samsung,link-rate\n");
+ video_info->max_link_rate = val;
+ if (of_property_read_u32(dp_node, "samsung,lane-count", &val) ||
+ !drm_dp_lane_count_is_valid(val))
+ return dev_err_probe(dp->dev, -EINVAL,
+ "Failed to get samsung,lane-count\n");
+ video_info->max_lane_count = val;
break;
}
+ if (analogix_dp_dt_parse_lanes_map(dp))
+ dev_dbg(dp->dev, "No valid data-lanes found, using default lane map\n");
+
return 0;
}
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
index c7997677a286..4560597604ad 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
@@ -137,6 +137,8 @@ struct video_info {
int max_link_rate;
enum link_lane_count_type max_lane_count;
+
+ u32 lane_map[LANE_COUNT4];
};
struct link_train {
@@ -177,7 +179,7 @@ struct analogix_dp_device {
/* analogix_dp_reg.c */
void analogix_dp_enable_video_mute(struct analogix_dp_device *dp, bool enable);
void analogix_dp_stop_video(struct analogix_dp_device *dp);
-void analogix_dp_lane_swap(struct analogix_dp_device *dp, bool enable);
+void analogix_dp_lane_mapping(struct analogix_dp_device *dp);
void analogix_dp_init_analog_param(struct analogix_dp_device *dp);
void analogix_dp_init_interrupt(struct analogix_dp_device *dp);
void analogix_dp_reset(struct analogix_dp_device *dp);
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
index ea8401293a23..c1344a3f013a 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
@@ -48,16 +48,15 @@ void analogix_dp_stop_video(struct analogix_dp_device *dp)
writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);
}
-void analogix_dp_lane_swap(struct analogix_dp_device *dp, bool enable)
+void analogix_dp_lane_mapping(struct analogix_dp_device *dp)
{
+ u32 *lane_map = dp->video_info.lane_map;
u32 reg;
- if (enable)
- reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 |
- LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3;
- else
- reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 |
- LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0;
+ reg = lane_map[0] << LANE0_MAP_SHIFT;
+ reg |= lane_map[1] << LANE1_MAP_SHIFT;
+ reg |= lane_map[2] << LANE2_MAP_SHIFT;
+ reg |= lane_map[3] << LANE3_MAP_SHIFT;
writel(reg, dp->reg_base + ANALOGIX_DP_LANE_MAP);
}
@@ -140,7 +139,7 @@ void analogix_dp_reset(struct analogix_dp_device *dp)
usleep_range(20, 30);
- analogix_dp_lane_swap(dp, 0);
+ analogix_dp_lane_mapping(dp);
writel(0x0, dp->reg_base + ANALOGIX_DP_SYS_CTL_1);
writel(0x40, dp->reg_base + ANALOGIX_DP_SYS_CTL_2);
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h
index 12735139046c..ac914e37089b 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h
@@ -209,6 +209,10 @@
#define LANE0_MAP_LOGIC_LANE_1 (0x1 << 0)
#define LANE0_MAP_LOGIC_LANE_2 (0x2 << 0)
#define LANE0_MAP_LOGIC_LANE_3 (0x3 << 0)
+#define LANE3_MAP_SHIFT (6)
+#define LANE2_MAP_SHIFT (4)
+#define LANE1_MAP_SHIFT (2)
+#define LANE0_MAP_SHIFT (0)
/* ANALOGIX_DP_ANALOG_CTL_1 */
#define TX_TERMINAL_CTRL_50_OHM (0x1 << 4)
diff --git a/drivers/gpu/drm/bridge/lontium-lt8713sx.c b/drivers/gpu/drm/bridge/lontium-lt8713sx.c
index bfff28883280..926f9e1e85bf 100644
--- a/drivers/gpu/drm/bridge/lontium-lt8713sx.c
+++ b/drivers/gpu/drm/bridge/lontium-lt8713sx.c
@@ -572,7 +572,7 @@ static void lt8713sx_remove(struct i2c_client *client)
}
static struct i2c_device_id lt8713sx_id[] = {
- { .name = "lontium,lt8713sx" },
+ { .name = "lt8713sx" },
{ /* sentinel */ }
};
diff --git a/drivers/gpu/drm/bridge/lontium-lt9211.c b/drivers/gpu/drm/bridge/lontium-lt9211.c
index 23682384daf4..285cda58f661 100644
--- a/drivers/gpu/drm/bridge/lontium-lt9211.c
+++ b/drivers/gpu/drm/bridge/lontium-lt9211.c
@@ -773,7 +773,7 @@ static void lt9211_remove(struct i2c_client *client)
}
static const struct i2c_device_id lt9211_id[] = {
- { .name = "lontium,lt9211" },
+ { .name = "lt9211" },
{ }
};
MODULE_DEVICE_TABLE(i2c, lt9211_id);
diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c
index 3ebd8992cd94..cdc2b188e2d8 100644
--- a/drivers/gpu/drm/bridge/lontium-lt9611.c
+++ b/drivers/gpu/drm/bridge/lontium-lt9611.c
@@ -1227,7 +1227,7 @@ static void lt9611_remove(struct i2c_client *client)
}
static const struct i2c_device_id lt9611_id[] = {
- { .name = "lontium,lt9611" },
+ { .name = "lt9611" },
{ }
};
MODULE_DEVICE_TABLE(i2c, lt9611_id);
diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
index 42a6503cd0f9..b3bb7f2cebb3 100644
--- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
+++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
@@ -899,7 +899,7 @@ static void lt9611uxc_remove(struct i2c_client *client)
}
static const struct i2c_device_id lt9611uxc_id[] = {
- { .name = "lontium,lt9611uxc" },
+ { .name = "lt9611uxc" },
{ /* sentinel */ }
};
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
index cfd1b18c06e6..c9568aea98dc 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
@@ -40,88 +40,6 @@
#define SCRAMB_POLL_DELAY_MS 3000
-/*
- * Unless otherwise noted, entries in this table are 100% optimization.
- * Values can be obtained from dw_hdmi_qp_compute_n() but that function is
- * slow so we pre-compute values we expect to see.
- *
- * The values for TMDS 25175, 25200, 27000, 54000, 74250 and 148500 kHz are
- * the recommended N values specified in the Audio chapter of the HDMI
- * specification.
- */
-static const struct dw_hdmi_audio_tmds_n {
- unsigned long tmds;
- unsigned int n_32k;
- unsigned int n_44k1;
- unsigned int n_48k;
-} common_tmds_n_table[] = {
- { .tmds = 25175000, .n_32k = 4576, .n_44k1 = 7007, .n_48k = 6864, },
- { .tmds = 25200000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, },
- { .tmds = 27000000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, },
- { .tmds = 28320000, .n_32k = 4096, .n_44k1 = 5586, .n_48k = 6144, },
- { .tmds = 30240000, .n_32k = 4096, .n_44k1 = 5642, .n_48k = 6144, },
- { .tmds = 31500000, .n_32k = 4096, .n_44k1 = 5600, .n_48k = 6144, },
- { .tmds = 32000000, .n_32k = 4096, .n_44k1 = 5733, .n_48k = 6144, },
- { .tmds = 33750000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, },
- { .tmds = 36000000, .n_32k = 4096, .n_44k1 = 5684, .n_48k = 6144, },
- { .tmds = 40000000, .n_32k = 4096, .n_44k1 = 5733, .n_48k = 6144, },
- { .tmds = 49500000, .n_32k = 4096, .n_44k1 = 5488, .n_48k = 6144, },
- { .tmds = 50000000, .n_32k = 4096, .n_44k1 = 5292, .n_48k = 6144, },
- { .tmds = 54000000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, },
- { .tmds = 65000000, .n_32k = 4096, .n_44k1 = 7056, .n_48k = 6144, },
- { .tmds = 68250000, .n_32k = 4096, .n_44k1 = 5376, .n_48k = 6144, },
- { .tmds = 71000000, .n_32k = 4096, .n_44k1 = 7056, .n_48k = 6144, },
- { .tmds = 72000000, .n_32k = 4096, .n_44k1 = 5635, .n_48k = 6144, },
- { .tmds = 73250000, .n_32k = 11648, .n_44k1 = 14112, .n_48k = 6144, },
- { .tmds = 74250000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, },
- { .tmds = 75000000, .n_32k = 4096, .n_44k1 = 5880, .n_48k = 6144, },
- { .tmds = 78750000, .n_32k = 4096, .n_44k1 = 5600, .n_48k = 6144, },
- { .tmds = 78800000, .n_32k = 4096, .n_44k1 = 5292, .n_48k = 6144, },
- { .tmds = 79500000, .n_32k = 4096, .n_44k1 = 4704, .n_48k = 6144, },
- { .tmds = 83500000, .n_32k = 4096, .n_44k1 = 7056, .n_48k = 6144, },
- { .tmds = 85500000, .n_32k = 4096, .n_44k1 = 5488, .n_48k = 6144, },
- { .tmds = 88750000, .n_32k = 4096, .n_44k1 = 14112, .n_48k = 6144, },
- { .tmds = 97750000, .n_32k = 4096, .n_44k1 = 14112, .n_48k = 6144, },
- { .tmds = 101000000, .n_32k = 4096, .n_44k1 = 7056, .n_48k = 6144, },
- { .tmds = 106500000, .n_32k = 4096, .n_44k1 = 4704, .n_48k = 6144, },
- { .tmds = 108000000, .n_32k = 4096, .n_44k1 = 5684, .n_48k = 6144, },
- { .tmds = 115500000, .n_32k = 4096, .n_44k1 = 5712, .n_48k = 6144, },
- { .tmds = 119000000, .n_32k = 4096, .n_44k1 = 5544, .n_48k = 6144, },
- { .tmds = 135000000, .n_32k = 4096, .n_44k1 = 5488, .n_48k = 6144, },
- { .tmds = 146250000, .n_32k = 11648, .n_44k1 = 6272, .n_48k = 6144, },
- { .tmds = 148500000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, },
- { .tmds = 154000000, .n_32k = 4096, .n_44k1 = 5544, .n_48k = 6144, },
- { .tmds = 162000000, .n_32k = 4096, .n_44k1 = 5684, .n_48k = 6144, },
-
- /* For 297 MHz+ HDMI spec have some other rule for setting N */
- { .tmds = 297000000, .n_32k = 3073, .n_44k1 = 4704, .n_48k = 5120, },
- { .tmds = 594000000, .n_32k = 3073, .n_44k1 = 9408, .n_48k = 10240,},
-
- /* End of table */
- { .tmds = 0, .n_32k = 0, .n_44k1 = 0, .n_48k = 0, },
-};
-
-/*
- * These are the CTS values as recommended in the Audio chapter of the HDMI
- * specification.
- */
-static const struct dw_hdmi_audio_tmds_cts {
- unsigned long tmds;
- unsigned int cts_32k;
- unsigned int cts_44k1;
- unsigned int cts_48k;
-} common_tmds_cts_table[] = {
- { .tmds = 25175000, .cts_32k = 28125, .cts_44k1 = 31250, .cts_48k = 28125, },
- { .tmds = 25200000, .cts_32k = 25200, .cts_44k1 = 28000, .cts_48k = 25200, },
- { .tmds = 27000000, .cts_32k = 27000, .cts_44k1 = 30000, .cts_48k = 27000, },
- { .tmds = 54000000, .cts_32k = 54000, .cts_44k1 = 60000, .cts_48k = 54000, },
- { .tmds = 74250000, .cts_32k = 74250, .cts_44k1 = 82500, .cts_48k = 74250, },
- { .tmds = 148500000, .cts_32k = 148500, .cts_44k1 = 165000, .cts_48k = 148500, },
-
- /* End of table */
- { .tmds = 0, .cts_32k = 0, .cts_44k1 = 0, .cts_48k = 0, },
-};
-
struct dw_hdmi_qp_i2c {
struct i2c_adapter adap;
@@ -213,130 +131,6 @@ static void dw_hdmi_qp_set_cts_n(struct dw_hdmi_qp *hdmi, unsigned int cts,
AUDPKT_ACR_CONTROL1);
}
-static int dw_hdmi_qp_match_tmds_n_table(struct dw_hdmi_qp *hdmi,
- unsigned long pixel_clk,
- unsigned long freq)
-{
- const struct dw_hdmi_audio_tmds_n *tmds_n = NULL;
- int i;
-
- for (i = 0; common_tmds_n_table[i].tmds != 0; i++) {
- if (pixel_clk == common_tmds_n_table[i].tmds) {
- tmds_n = &common_tmds_n_table[i];
- break;
- }
- }
-
- if (!tmds_n)
- return -ENOENT;
-
- switch (freq) {
- case 32000:
- return tmds_n->n_32k;
- case 44100:
- case 88200:
- case 176400:
- return (freq / 44100) * tmds_n->n_44k1;
- case 48000:
- case 96000:
- case 192000:
- return (freq / 48000) * tmds_n->n_48k;
- default:
- return -ENOENT;
- }
-}
-
-static u32 dw_hdmi_qp_audio_math_diff(unsigned int freq, unsigned int n,
- unsigned int pixel_clk)
-{
- u64 cts = mul_u32_u32(pixel_clk, n);
-
- return do_div(cts, 128 * freq);
-}
-
-static unsigned int dw_hdmi_qp_compute_n(struct dw_hdmi_qp *hdmi,
- unsigned long pixel_clk,
- unsigned long freq)
-{
- unsigned int min_n = DIV_ROUND_UP((128 * freq), 1500);
- unsigned int max_n = (128 * freq) / 300;
- unsigned int ideal_n = (128 * freq) / 1000;
- unsigned int best_n_distance = ideal_n;
- unsigned int best_n = 0;
- u64 best_diff = U64_MAX;
- int n;
-
- /* If the ideal N could satisfy the audio math, then just take it */
- if (dw_hdmi_qp_audio_math_diff(freq, ideal_n, pixel_clk) == 0)
- return ideal_n;
-
- for (n = min_n; n <= max_n; n++) {
- u64 diff = dw_hdmi_qp_audio_math_diff(freq, n, pixel_clk);
-
- if (diff < best_diff ||
- (diff == best_diff && abs(n - ideal_n) < best_n_distance)) {
- best_n = n;
- best_diff = diff;
- best_n_distance = abs(best_n - ideal_n);
- }
-
- /*
- * The best N already satisfy the audio math, and also be
- * the closest value to ideal N, so just cut the loop.
- */
- if (best_diff == 0 && (abs(n - ideal_n) > best_n_distance))
- break;
- }
-
- return best_n;
-}
-
-static unsigned int dw_hdmi_qp_find_n(struct dw_hdmi_qp *hdmi, unsigned long pixel_clk,
- unsigned long sample_rate)
-{
- int n = dw_hdmi_qp_match_tmds_n_table(hdmi, pixel_clk, sample_rate);
-
- if (n > 0)
- return n;
-
- dev_warn(hdmi->dev, "Rate %lu missing; compute N dynamically\n",
- pixel_clk);
-
- return dw_hdmi_qp_compute_n(hdmi, pixel_clk, sample_rate);
-}
-
-static unsigned int dw_hdmi_qp_find_cts(struct dw_hdmi_qp *hdmi, unsigned long pixel_clk,
- unsigned long sample_rate)
-{
- const struct dw_hdmi_audio_tmds_cts *tmds_cts = NULL;
- int i;
-
- for (i = 0; common_tmds_cts_table[i].tmds != 0; i++) {
- if (pixel_clk == common_tmds_cts_table[i].tmds) {
- tmds_cts = &common_tmds_cts_table[i];
- break;
- }
- }
-
- if (!tmds_cts)
- return 0;
-
- switch (sample_rate) {
- case 32000:
- return tmds_cts->cts_32k;
- case 44100:
- case 88200:
- case 176400:
- return tmds_cts->cts_44k1;
- case 48000:
- case 96000:
- case 192000:
- return tmds_cts->cts_48k;
- default:
- return -ENOENT;
- }
-}
-
static void dw_hdmi_qp_set_audio_interface(struct dw_hdmi_qp *hdmi,
struct hdmi_codec_daifmt *fmt,
struct hdmi_codec_params *hparms)
@@ -456,8 +250,7 @@ static void dw_hdmi_qp_set_sample_rate(struct dw_hdmi_qp *hdmi, unsigned long lo
{
unsigned int n, cts;
- n = dw_hdmi_qp_find_n(hdmi, tmds_char_rate, sample_rate);
- cts = dw_hdmi_qp_find_cts(hdmi, tmds_char_rate, sample_rate);
+ drm_hdmi_acr_get_n_cts(tmds_char_rate, sample_rate, &n, &cts);
dw_hdmi_qp_set_cts_n(hdmi, cts, n);
}
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
index 41c217074cc3..b4a4dd83eb5c 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
@@ -11,6 +11,8 @@
* = 1x Single-link DSI ~ 2x Single-link or 1x Dual-link LVDS
* - Supported
* - Dual-link LVDS mode tested
+ * - Single-link to LVDS Channel A tested
+ * - Single-link to LVDS Channel B tested
* - 2x Single-link LVDS mode unsupported
* (should be easy to add by someone who has the HW)
* - SN65DSI85
@@ -162,7 +164,7 @@ struct sn65dsi83 {
struct gpio_desc *enable_gpio;
struct regulator *vcc;
bool lvds_dual_link;
- bool lvds_dual_link_even_odd_swap;
+ bool lvds_channel_swap;
int lvds_vod_swing_conf[2];
int lvds_term_conf[2];
int irq;
@@ -642,7 +644,7 @@ static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge,
REG_LVDS_VCOM_CHA_LVDS_VOD_SWING(ctx->lvds_vod_swing_conf[CHANNEL_A]) |
REG_LVDS_VCOM_CHB_LVDS_VOD_SWING(ctx->lvds_vod_swing_conf[CHANNEL_B]));
regmap_write(ctx->regmap, REG_LVDS_LANE,
- (ctx->lvds_dual_link_even_odd_swap ?
+ (ctx->lvds_channel_swap ?
REG_LVDS_LANE_EVEN_ODD_SWAP : 0) |
(ctx->lvds_term_conf[CHANNEL_A] ?
REG_LVDS_LANE_CHA_LVDS_TERM : 0) |
@@ -876,6 +878,7 @@ static int sn65dsi83_parse_dt(struct sn65dsi83 *ctx, enum sn65dsi83_model model)
{
struct drm_bridge *panel_bridge;
struct device *dev = ctx->dev;
+ u32 output_port = 2;
int ret;
ret = sn65dsi83_parse_lvds_endpoint(ctx, CHANNEL_A);
@@ -887,29 +890,38 @@ static int sn65dsi83_parse_dt(struct sn65dsi83 *ctx, enum sn65dsi83_model model)
return ret;
ctx->lvds_dual_link = false;
- ctx->lvds_dual_link_even_odd_swap = false;
+ ctx->lvds_channel_swap = false;
if (model != MODEL_SN65DSI83) {
- struct device_node *port2, *port3;
+ struct device_node *port0, *port1, *port2, *port3;
int dual_link;
+ port0 = of_graph_get_port_by_id(dev->of_node, 0);
+ port1 = of_graph_get_port_by_id(dev->of_node, 1);
port2 = of_graph_get_port_by_id(dev->of_node, 2);
port3 = of_graph_get_port_by_id(dev->of_node, 3);
dual_link = drm_of_lvds_get_dual_link_pixel_order(port2, port3);
- of_node_put(port2);
- of_node_put(port3);
if (dual_link == DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS) {
- ctx->lvds_dual_link = true;
/* Odd pixels to LVDS Channel A, even pixels to B */
- ctx->lvds_dual_link_even_odd_swap = false;
- } else if (dual_link == DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS) {
ctx->lvds_dual_link = true;
+ } else if (dual_link == DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS) {
/* Even pixels to LVDS Channel A, odd pixels to B */
- ctx->lvds_dual_link_even_odd_swap = true;
+ ctx->lvds_dual_link = true;
+ ctx->lvds_channel_swap = true;
+ } else if (port0 && !port1 && port2 && !port3) {
+ /* DSI Channel A to LVDS Channel A */
+ } else if (port0 && !port1 && !port2 && port3) {
+ /* DSI Channel A to LVDS Channel B */
+ ctx->lvds_channel_swap = true;
+ output_port = 3;
}
+ of_node_put(port0);
+ of_node_put(port1);
+ of_node_put(port2);
+ of_node_put(port3);
}
- panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 2, 0);
+ panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, output_port, 0);
if (IS_ERR(panel_bridge))
return dev_err_probe(dev, PTR_ERR(panel_bridge), "Failed to get panel bridge\n");
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 9990a836d0b6..1331efb4876c 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -7852,3 +7852,50 @@ bool drm_edid_is_digital(const struct drm_edid *drm_edid)
drm_edid->edid->input & DRM_EDID_INPUT_DIGITAL;
}
EXPORT_SYMBOL(drm_edid_is_digital);
+
+/**
+ * drm_edid_detect_panel_size - Get a panel's size from EDID
+ * @drm_edid: EDID of the panel.
+ * @width: Returns the panel's width in pixels per scanline, if given
+ * @height: Returns the panel's height in scanlines, if given
+ *
+ * This function detects the preferred size of a panel from the given
+ * EDID. There is no such information stored in the EDID block directly,
+ * but the preferred mode often corresponds to the panel's native geometry.
+ *
+ * This helper should only be used during initialization before the
+ * connector is available. For regular use, retrieve the available display
+ * modes with the connector functions.
+ *
+ * Return: Zero on success, or a negative errno code otherwise.
+ */
+int drm_edid_detect_panel_size(const struct drm_edid *drm_edid,
+ unsigned int *width, unsigned int *height)
+{
+ const struct edid *edid = drm_edid->edid;
+ const struct detailed_timing *dt;
+ const struct detailed_pixel_timing *pt;
+
+ /*
+ * Use display mode from the Preferred Timing Descriptor. For old
+ * and obscure displays, we might need better heuristics.
+ */
+
+ if (edid->revision < 4 || !(edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING))
+ return -EINVAL; /* no Preferred Timing Descriptor */
+
+ dt = &edid->detailed_timings[0];
+
+ if (!is_detailed_timing_descriptor(dt))
+ return -EINVAL;
+
+ pt = &dt->data.pixel_data;
+
+ if (width)
+ *width = (pt->hactive_hblank_hi & 0xf0) << 4 | pt->hactive_lo;
+ if (height)
+ *height = (pt->vactive_vblank_hi & 0xf0) << 4 | pt->vactive_lo;
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_edid_detect_panel_size);
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index b0e0e4118573..e263982f78ce 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -1648,15 +1648,13 @@ EXPORT_SYMBOL(drm_gem_lru_move_tail);
* @nr_to_scan: The number of pages to try to reclaim
* @remaining: The number of pages left to reclaim, should be initialized by caller
* @shrink: Callback to try to shrink/reclaim the object.
- * @ticket: Optional ww_acquire_ctx context to use for locking
*/
unsigned long
drm_gem_lru_scan(struct drm_device *dev,
struct drm_gem_lru *lru,
unsigned int nr_to_scan,
unsigned long *remaining,
- bool (*shrink)(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket),
- struct ww_acquire_ctx *ticket)
+ bool (*shrink)(struct drm_gem_object *obj))
{
struct drm_gem_lru still_in_lru;
struct drm_gem_object *obj;
@@ -1689,20 +1687,17 @@ drm_gem_lru_scan(struct drm_device *dev,
*/
mutex_unlock(&dev->gem_lru_mutex);
- if (ticket)
- ww_acquire_init(ticket, &reservation_ww_class);
-
/*
* Note that this still needs to be trylock, since we can
* hit shrinker in response to trying to get backing pages
* for this obj (ie. while it's lock is already held)
*/
- if (!ww_mutex_trylock(&obj->resv->lock, ticket)) {
+ if (!ww_mutex_trylock(&obj->resv->lock, NULL)) {
*remaining += obj->size >> PAGE_SHIFT;
goto tail;
}
- if (shrink(obj, ticket)) {
+ if (shrink(obj)) {
freed += obj->size >> PAGE_SHIFT;
/*
@@ -1726,9 +1721,6 @@ drm_gem_lru_scan(struct drm_device *dev,
dma_resv_unlock(obj->resv);
- if (ticket)
- ww_acquire_fini(ticket);
-
tail:
drm_gem_object_put(obj);
mutex_lock(&dev->gem_lru_mutex);
diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c
index 0df75a4a7739..f79484b9d593 100644
--- a/drivers/gpu/drm/gma500/psb_intel_display.c
+++ b/drivers/gpu/drm/gma500/psb_intel_display.c
@@ -9,8 +9,11 @@
#include <linux/delay.h>
#include <linux/i2c.h>
+#include <drm/drm_fourcc.h>
#include <drm/drm_modeset_helper.h>
#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_plane.h>
+#include <drm/drm_plane_helper.h>
#include <drm/drm_print.h>
#include "framebuffer.h"
@@ -471,11 +474,25 @@ out:
REG_WRITE(base[gma_crtc->pipe], 0);
}
+/*
+ * The display engine programs the primary plane with
+ * DISPPLANE_32BPP_NO_ALPHA, so no formats with alpha.
+ */
+static const uint32_t gma_primary_formats[] = {
+ DRM_FORMAT_XRGB8888,
+};
+
+static const struct drm_plane_funcs gma_primary_plane_funcs = {
+ .update_plane = drm_plane_helper_update_primary,
+ .disable_plane = drm_plane_helper_disable_primary,
+};
+
void psb_intel_crtc_init(struct drm_device *dev, int pipe,
struct psb_intel_mode_device *mode_dev)
{
struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct gma_crtc *gma_crtc;
+ struct drm_plane *primary;
int i;
/* We allocate a extra array of drm_connector pointers
@@ -494,7 +511,17 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
return;
}
- drm_crtc_init(dev, &gma_crtc->base, &gma_crtc_funcs);
+ primary = drmm_universal_plane_alloc(dev, struct drm_plane, dev, 0,
+ &gma_primary_plane_funcs,
+ gma_primary_formats,
+ ARRAY_SIZE(gma_primary_formats),
+ NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
+ if (IS_ERR(primary))
+ goto err_free_crtc;
+
+ if (drm_crtc_init_with_planes(dev, &gma_crtc->base, primary, NULL,
+ &gma_crtc_funcs, NULL))
+ goto err_free_crtc;
/* Set the CRTC clock functions from chip specific data */
gma_crtc->clock_funcs = dev_priv->ops->clock_funcs;
@@ -524,6 +551,11 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
/* Set to true so that the pipe is forced off on initial config. */
gma_crtc->active = true;
+ return;
+
+err_free_crtc:
+ kfree(gma_crtc->crtc_state);
+ kfree(gma_crtc);
}
struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, int pipe)
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
index 33402cf54072..7849abd0488e 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
@@ -20,6 +20,7 @@
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_vblank.h>
+#include <drm/drm_vblank_helper.h>
#include "hibmc_drm_drv.h"
#include "hibmc_drm_regs.h"
@@ -420,19 +421,6 @@ static void hibmc_crtc_atomic_begin(struct drm_crtc *crtc,
/* We can add more initialization as needed. */
}
-static void hibmc_crtc_atomic_flush(struct drm_crtc *crtc,
- struct drm_atomic_commit *state)
-
-{
- unsigned long flags;
-
- spin_lock_irqsave(&crtc->dev->event_lock, flags);
- if (crtc->state->event)
- drm_crtc_send_vblank_event(crtc, crtc->state->event);
- crtc->state->event = NULL;
- spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
-}
-
static int hibmc_crtc_enable_vblank(struct drm_crtc *crtc)
{
struct hibmc_drm_private *priv = to_hibmc_drm_private(crtc->dev);
@@ -502,7 +490,7 @@ static const struct drm_crtc_funcs hibmc_crtc_funcs = {
static const struct drm_crtc_helper_funcs hibmc_crtc_helper_funcs = {
.mode_set_nofb = hibmc_crtc_mode_set_nofb,
.atomic_begin = hibmc_crtc_atomic_begin,
- .atomic_flush = hibmc_crtc_atomic_flush,
+ .atomic_flush = drm_crtc_vblank_atomic_flush,
.atomic_enable = hibmc_crtc_atomic_enable,
.atomic_disable = hibmc_crtc_atomic_disable,
.mode_valid = hibmc_crtc_mode_valid,
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index 4d85c89f3f88..602930964e93 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -49,9 +49,10 @@ static irqreturn_t hibmc_interrupt(int irq, void *arg)
writel(HIBMC_RAW_INTERRUPT_VBLANK(1),
priv->mmio + HIBMC_RAW_INTERRUPT);
drm_handle_vblank(dev, 0);
+ return IRQ_HANDLED;
}
- return IRQ_HANDLED;
+ return IRQ_NONE;
}
static irqreturn_t hibmc_dp_interrupt(int irq, void *arg)
@@ -67,7 +68,7 @@ static irqreturn_t hibmc_dp_interrupt(int irq, void *arg)
return IRQ_WAKE_THREAD;
}
- return IRQ_HANDLED;
+ return IRQ_NONE;
}
static int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev,
diff --git a/drivers/gpu/drm/msm/msm_gem_shrinker.c b/drivers/gpu/drm/msm/msm_gem_shrinker.c
index 9d2788f79ace..3514d5c84989 100644
--- a/drivers/gpu/drm/msm/msm_gem_shrinker.c
+++ b/drivers/gpu/drm/msm/msm_gem_shrinker.c
@@ -102,7 +102,7 @@ out_unlock:
}
static bool
-purge(struct drm_gem_object *obj, struct ww_acquire_ctx *unused)
+purge(struct drm_gem_object *obj)
{
if (!is_purgeable(to_msm_bo(obj)))
return false;
@@ -114,7 +114,7 @@ purge(struct drm_gem_object *obj, struct ww_acquire_ctx *unused)
}
static bool
-evict(struct drm_gem_object *obj, struct ww_acquire_ctx *unused)
+evict(struct drm_gem_object *obj)
{
if (is_unevictable(to_msm_bo(obj)))
return false;
@@ -133,21 +133,21 @@ wait_for_idle(struct drm_gem_object *obj)
}
static bool
-active_purge(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket)
+active_purge(struct drm_gem_object *obj)
{
if (!wait_for_idle(obj))
return false;
- return purge(obj, ticket);
+ return purge(obj);
}
static bool
-active_evict(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket)
+active_evict(struct drm_gem_object *obj)
{
if (!wait_for_idle(obj))
return false;
- return evict(obj, ticket);
+ return evict(obj);
}
static unsigned long
@@ -156,7 +156,7 @@ msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
struct msm_drm_private *priv = shrinker->private_data;
struct {
struct drm_gem_lru *lru;
- bool (*shrink)(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket);
+ bool (*shrink)(struct drm_gem_object *obj);
bool cond;
unsigned long freed;
unsigned long remaining;
@@ -180,8 +180,7 @@ msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
stages[i].freed =
drm_gem_lru_scan(priv->dev, stages[i].lru, nr,
&stages[i].remaining,
- stages[i].shrink,
- NULL);
+ stages[i].shrink);
nr -= stages[i].freed;
freed += stages[i].freed;
remaining += stages[i].remaining;
@@ -222,7 +221,7 @@ msm_gem_shrinker_shrink(struct drm_device *dev, unsigned long nr_to_scan)
static const int vmap_shrink_limit = 15;
static bool
-vmap_shrink(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket)
+vmap_shrink(struct drm_gem_object *obj)
{
if (!is_vunmapable(to_msm_bo(obj)))
return false;
@@ -250,8 +249,7 @@ msm_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr)
unmapped += drm_gem_lru_scan(priv->dev, lrus[idx],
vmap_shrink_limit - unmapped,
&remaining,
- vmap_shrink,
- NULL);
+ vmap_shrink);
}
*(unsigned long *)ptr += unmapped;
diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c
index 72908be5e144..c07a44057e42 100644
--- a/drivers/gpu/drm/panthor/panthor_gem.c
+++ b/drivers/gpu/drm/panthor/panthor_gem.c
@@ -1410,8 +1410,7 @@ panthor_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc)
return count ? count : SHRINK_EMPTY;
}
-static bool panthor_gem_try_evict_no_resv_wait(struct drm_gem_object *obj,
- struct ww_acquire_ctx *ticket)
+static bool panthor_gem_try_evict_no_resv_wait(struct drm_gem_object *obj)
{
/*
* Track last locked entry for unwinding locks in error and
@@ -1497,8 +1496,7 @@ out_unlock:
return ret == 0;
}
-static bool panthor_gem_try_evict(struct drm_gem_object *obj,
- struct ww_acquire_ctx *ticket)
+static bool panthor_gem_try_evict(struct drm_gem_object *obj)
{
struct panthor_gem_object *bo = to_panthor_bo(obj);
@@ -1506,7 +1504,7 @@ static bool panthor_gem_try_evict(struct drm_gem_object *obj,
if (dma_resv_wait_timeout(obj->resv, DMA_RESV_USAGE_BOOKKEEP, false, 10) <= 0)
return false;
- return panthor_gem_try_evict_no_resv_wait(&bo->base, ticket);
+ return panthor_gem_try_evict_no_resv_wait(&bo->base);
}
static unsigned long
@@ -1521,13 +1519,13 @@ panthor_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
freed += drm_gem_lru_scan(&ptdev->base, &ptdev->reclaim.unused,
sc->nr_to_scan - freed, &remaining,
- panthor_gem_try_evict_no_resv_wait, NULL);
+ panthor_gem_try_evict_no_resv_wait);
if (freed >= sc->nr_to_scan)
goto out;
freed += drm_gem_lru_scan(&ptdev->base, &ptdev->reclaim.mmapped,
sc->nr_to_scan - freed, &remaining,
- panthor_gem_try_evict_no_resv_wait, NULL);
+ panthor_gem_try_evict_no_resv_wait);
if (freed >= sc->nr_to_scan)
goto out;
@@ -1541,7 +1539,7 @@ panthor_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
freed += drm_gem_lru_scan(&ptdev->base, &ptdev->reclaim.gpu_mapped_shared,
sc->nr_to_scan - freed, &remaining,
- panthor_gem_try_evict, NULL);
+ panthor_gem_try_evict);
out:
#ifdef CONFIG_DEBUG_FS
diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/panthor/panthor_mmu.c
index 6f7b83dca6a5..d75d575473da 100644
--- a/drivers/gpu/drm/panthor/panthor_mmu.c
+++ b/drivers/gpu/drm/panthor/panthor_mmu.c
@@ -3280,8 +3280,7 @@ int panthor_vm_prepare_mapped_bos_resvs(struct drm_exec *exec, struct panthor_vm
unsigned long
panthor_mmu_reclaim_priv_bos(struct panthor_device *ptdev,
unsigned int nr_to_scan, unsigned long *remaining,
- bool (*shrink)(struct drm_gem_object *,
- struct ww_acquire_ctx *))
+ bool (*shrink)(struct drm_gem_object *))
{
unsigned long freed = 0;
LIST_HEAD(remaining_vms);
@@ -3307,7 +3306,7 @@ panthor_mmu_reclaim_priv_bos(struct panthor_device *ptdev,
freed += drm_gem_lru_scan(&ptdev->base, &vm->reclaim.lru,
nr_to_scan - freed,
- remaining, shrink, NULL);
+ remaining, shrink);
mutex_lock(&ptdev->base.gem_lru_mutex);
diff --git a/drivers/gpu/drm/panthor/panthor_mmu.h b/drivers/gpu/drm/panthor/panthor_mmu.h
index 3522fbbce369..abc36e7204be 100644
--- a/drivers/gpu/drm/panthor/panthor_mmu.h
+++ b/drivers/gpu/drm/panthor/panthor_mmu.h
@@ -52,8 +52,7 @@ int panthor_vm_evict_bo_mappings_locked(struct panthor_gem_object *bo);
unsigned long
panthor_mmu_reclaim_priv_bos(struct panthor_device *ptdev,
unsigned int nr_to_scan, unsigned long *remaining,
- bool (*shrink)(struct drm_gem_object *,
- struct ww_acquire_ctx *));
+ bool (*shrink)(struct drm_gem_object *));
int panthor_vm_prepare_mapped_bos_resvs(struct drm_exec *exec,
struct panthor_vm *vm,
u32 slot_count);
diff --git a/drivers/gpu/drm/sysfb/efidrm.c b/drivers/gpu/drm/sysfb/efidrm.c
index 3f9cd5d03efb..8b19f437308e 100644
--- a/drivers/gpu/drm/sysfb/efidrm.c
+++ b/drivers/gpu/drm/sysfb/efidrm.c
@@ -152,6 +152,7 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv,
const struct screen_info *si;
const struct drm_format_info *format;
int width, height, stride;
+ unsigned int panel_width, panel_height;
s64 vsize;
u64 mem_flags;
struct resource resbuf;
@@ -217,6 +218,20 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv,
if (drm_edid_header_is_valid(dpy->edid.dummy) == 8)
sysfb->edid = dpy->edid.dummy;
#endif
+
+ panel_width = width;
+ panel_height = height;
+
+ if (sysfb->edid) {
+ const struct drm_edid *drm_edid;
+
+ drm_edid = drm_edid_alloc(sysfb->edid, EDID_LENGTH);
+ if (drm_edid) {
+ drm_edid_detect_panel_size(drm_edid, &panel_width, &panel_height);
+ drm_edid_free(drm_edid);
+ }
+ }
+
sysfb->fb_mode = drm_sysfb_mode(width, height, 0, 0);
sysfb->fb_format = format;
sysfb->fb_pitch = stride;
@@ -340,7 +355,7 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv,
drm_connector_helper_add(connector, &efidrm_connector_helper_funcs);
drm_connector_set_panel_orientation_with_quirk(connector,
DRM_MODE_PANEL_ORIENTATION_UNKNOWN,
- width, height);
+ panel_width, panel_height);
if (sysfb->edid)
drm_connector_attach_edid_property(connector);
diff --git a/drivers/gpu/drm/sysfb/ofdrm.c b/drivers/gpu/drm/sysfb/ofdrm.c
index 9d60db45139c..c41255569854 100644
--- a/drivers/gpu/drm/sysfb/ofdrm.c
+++ b/drivers/gpu/drm/sysfb/ofdrm.c
@@ -229,7 +229,7 @@ static const u8 *display_get_edid_of(struct drm_device *dev, struct device_node
{
int ret = of_property_read_u8_array(of_node, "EDID", buf, EDID_LENGTH);
- if (ret)
+ if (ret || drm_edid_header_is_valid(buf) != 8)
return NULL;
return buf;
}
@@ -828,6 +828,7 @@ static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv,
enum ofdrm_model model;
bool big_endian;
int width, height, depth, linebytes;
+ unsigned int panel_width, panel_height;
const struct drm_format_info *format;
u64 address;
const u8 *edid;
@@ -998,6 +999,19 @@ static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv,
sysfb->fb_gamma_lut_size = OFDRM_GAMMA_LUT_SIZE;
sysfb->edid = edid;
+ panel_width = width;
+ panel_height = height;
+
+ if (sysfb->edid) {
+ const struct drm_edid *drm_edid;
+
+ drm_edid = drm_edid_alloc(sysfb->edid, EDID_LENGTH);
+ if (drm_edid) {
+ drm_edid_detect_panel_size(drm_edid, &panel_width, &panel_height);
+ drm_edid_free(drm_edid);
+ }
+ }
+
drm_dbg(dev, "display mode={" DRM_MODE_FMT "}\n", DRM_MODE_ARG(&sysfb->fb_mode));
drm_dbg(dev, "framebuffer format=%p4cc, size=%dx%d, linebytes=%d byte\n",
&format->format, width, height, linebytes);
@@ -1069,7 +1083,7 @@ static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv,
drm_connector_helper_add(connector, &ofdrm_connector_helper_funcs);
drm_connector_set_panel_orientation_with_quirk(connector,
DRM_MODE_PANEL_ORIENTATION_UNKNOWN,
- width, height);
+ panel_width, panel_height);
if (edid)
drm_connector_attach_edid_property(connector);
diff --git a/drivers/gpu/drm/sysfb/vesadrm.c b/drivers/gpu/drm/sysfb/vesadrm.c
index 6a67b2d2e451..f6358a0a68bd 100644
--- a/drivers/gpu/drm/sysfb/vesadrm.c
+++ b/drivers/gpu/drm/sysfb/vesadrm.c
@@ -402,6 +402,7 @@ static struct vesadrm_device *vesadrm_device_create(struct drm_driver *drv,
const struct screen_info *si;
const struct drm_format_info *format;
int width, height, stride;
+ unsigned int panel_width, panel_height;
s64 vsize;
struct resource resbuf;
struct resource *res;
@@ -484,6 +485,20 @@ static struct vesadrm_device *vesadrm_device_create(struct drm_driver *drv,
if (drm_edid_header_is_valid(dpy->edid.dummy) == 8)
sysfb->edid = dpy->edid.dummy;
#endif
+
+ panel_width = width;
+ panel_height = height;
+
+ if (sysfb->edid) {
+ const struct drm_edid *drm_edid;
+
+ drm_edid = drm_edid_alloc(sysfb->edid, EDID_LENGTH);
+ if (drm_edid) {
+ drm_edid_detect_panel_size(drm_edid, &panel_width, &panel_height);
+ drm_edid_free(drm_edid);
+ }
+ }
+
sysfb->fb_mode = drm_sysfb_mode(width, height, 0, 0);
sysfb->fb_format = format;
sysfb->fb_pitch = stride;
@@ -585,7 +600,7 @@ static struct vesadrm_device *vesadrm_device_create(struct drm_driver *drv,
drm_connector_helper_add(connector, &vesadrm_connector_helper_funcs);
drm_connector_set_panel_orientation_with_quirk(connector,
DRM_MODE_PANEL_ORIENTATION_UNKNOWN,
- width, height);
+ panel_width, panel_height);
if (sysfb->edid)
drm_connector_attach_edid_property(connector);
diff --git a/include/drm/display/drm_dp_helper.h b/include/drm/display/drm_dp_helper.h
index ab16c1be3900..5b05a7fbe174 100644
--- a/include/drm/display/drm_dp_helper.h
+++ b/include/drm/display/drm_dp_helper.h
@@ -139,6 +139,12 @@ bool drm_dp_as_sdp_supported(struct drm_dp_aux *aux, const u8 dpcd[DP_RECEIVER_C
int drm_dp_psr_setup_time(const u8 psr_cap[EDP_PSR_RECEIVER_CAP_SIZE]);
+static inline bool
+drm_dp_lane_count_is_valid(int lane_count)
+{
+ return lane_count == 1 || lane_count == 2 || lane_count == 4;
+}
+
static inline int
drm_dp_max_link_rate(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
{
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index 04f7a7f1f108..a2617aa34edf 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -490,5 +490,7 @@ u32 drm_edid_get_panel_id(const struct drm_edid *drm_edid);
bool drm_edid_match(const struct drm_edid *drm_edid,
const struct drm_edid_ident *ident);
bool drm_edid_has_quirk(struct drm_connector *connector, enum drm_edid_quirk quirk);
+int drm_edid_detect_panel_size(const struct drm_edid *drm_edid,
+ unsigned int *width, unsigned int *height);
#endif /* __DRM_EDID_H__ */
diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
index 885244e375d3..c135253ab6cb 100644
--- a/include/drm/drm_gem.h
+++ b/include/drm/drm_gem.h
@@ -616,8 +616,7 @@ drm_gem_lru_scan(struct drm_device *dev,
struct drm_gem_lru *lru,
unsigned int nr_to_scan,
unsigned long *remaining,
- bool (*shrink)(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket),
- struct ww_acquire_ctx *ticket);
+ bool (*shrink)(struct drm_gem_object *obj));
int drm_gem_evict_locked(struct drm_gem_object *obj);
diff --git a/sound/soc/ti/omap-hdmi.c b/sound/soc/ti/omap-hdmi.c
index c32ec7c0b0cf..2cabd4cc5b0b 100644
--- a/sound/soc/ti/omap-hdmi.c
+++ b/sound/soc/ti/omap-hdmi.c
@@ -405,7 +405,6 @@ static int omap_hdmi_audio_probe(struct platform_device *pdev)
card->dev = dev;
atomic_set(&ad->jack_state, -1);
- ad->card = card;
snd_soc_card_set_drvdata(card, ad);
ret = devm_snd_soc_register_card(dev, card);