diff options
| author | Dave Airlie <airlied@redhat.com> | 2026-09-11 18:45:13 +1000 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2026-09-11 18:45:19 +1000 |
| commit | 14d6074f52d3af2b27565e6957b92dceeb8b00da (patch) | |
| tree | 507929b200eb41c10c133839fd366a75f30cbfb1 | |
| parent | f5c6fdfa1f4460c5714cd4996c6aa280d25399ca (diff) | |
| parent | 75ee88dae80d8c1141ef850bda9a26dbd1fe3c21 (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
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); |
