diff --git a/arch/arm64/boot/dts/apple/t600x-die0.dtsi b/arch/arm64/boot/dts/apple/t600x-die0.dtsi index 637e052e5db3c3..db26b06124dc46 100644 --- a/arch/arm64/boot/dts/apple/t600x-die0.dtsi +++ b/arch/arm64/boot/dts/apple/t600x-die0.dtsi @@ -525,6 +525,7 @@ <0x3 0x8b344000 0x0 0x4000>, <0x3 0x8b800000 0x0 0x800000>; apple,bw-scratch = <&pmgr_dcp 0 4 0x988>; + apple,iomfb-surfaces = <0x3>; #ifdef APPLE_USE_PMP power-domains = <&pmp_report_disp0>; #else diff --git a/arch/arm64/boot/dts/apple/t600x-dieX.dtsi b/arch/arm64/boot/dts/apple/t600x-dieX.dtsi index e222d63b37d320..2df236c1e482c6 100644 --- a/arch/arm64/boot/dts/apple/t600x-dieX.dtsi +++ b/arch/arm64/boot/dts/apple/t600x-dieX.dtsi @@ -103,6 +103,7 @@ <0x2 0x89344000 0x0 0x4000>, <0x2 0x89800000 0x0 0x800000>; apple,bw-scratch = <&pmgr_dcp 0 4 0x990>; + apple,iomfb-surfaces = <0x3>; #ifdef APPLE_USE_PMP power-domains = <&DIE_NODE(pmp_report_dispext0)>; #else @@ -184,6 +185,7 @@ <0x2 0x8c344000 0x0 0x4000>, <0x2 0x8c800000 0x0 0x800000>; apple,bw-scratch = <&pmgr_dcp 0 4 0x998>; + apple,iomfb-surfaces = <0x3>; #ifdef APPLE_USE_PMP power-domains = <&DIE_NODE(pmp_report_dispext1)>; #else diff --git a/arch/arm64/boot/dts/apple/t602x-die0.dtsi b/arch/arm64/boot/dts/apple/t602x-die0.dtsi index 8938dd90693c4d..9b27b1d2a190a4 100644 --- a/arch/arm64/boot/dts/apple/t602x-die0.dtsi +++ b/arch/arm64/boot/dts/apple/t602x-die0.dtsi @@ -624,6 +624,7 @@ <0x3 0x89344000 0x0 0x4000>, <0x3 0x89800000 0x0 0x800000>; apple,bw-scratch = <&pmgr_dcp 0 4 0x1208>; + apple,iomfb-surfaces = <0xb>; #ifdef APPLE_USE_PMP power-domains = <&pmp_report_disp0>; #else diff --git a/arch/arm64/boot/dts/apple/t602x-dieX.dtsi b/arch/arm64/boot/dts/apple/t602x-dieX.dtsi index d916c0b106d109..62d9ede3e02fe4 100644 --- a/arch/arm64/boot/dts/apple/t602x-dieX.dtsi +++ b/arch/arm64/boot/dts/apple/t602x-dieX.dtsi @@ -102,6 +102,7 @@ <0x2 0x89344000 0x0 0x4000>, <0x2 0x89800000 0x0 0x800000>; apple,bw-scratch = <&pmgr_dcp 0 4 0x1210>; + apple,iomfb-surfaces = <0xb>; #ifdef APPLE_USE_PMP power-domains = <&DIE_NODE(pmp_report_dispext0)>; #else @@ -254,6 +255,7 @@ <0x3 0x15344000 0x0 0x4000>, <0x3 0x15800000 0x0 0x800000>; apple,bw-scratch = <&pmgr_dcp 0 4 0x1218>; + apple,iomfb-surfaces = <0xb>; #ifdef APPLE_USE_PMP power-domains = <&DIE_NODE(pmp_report_dispext1)>; #else diff --git a/arch/arm64/boot/dts/apple/t8103.dtsi b/arch/arm64/boot/dts/apple/t8103.dtsi index dfb5f737a420b3..5334209728bc8e 100644 --- a/arch/arm64/boot/dts/apple/t8103.dtsi +++ b/arch/arm64/boot/dts/apple/t8103.dtsi @@ -659,6 +659,7 @@ <0x2 0x3b3d0000 0x0 0x4000>; apple,bw-scratch = <&pmgr_dcp 0 5 0x14>; apple,bw-doorbell = <&pmgr_dcp 1 6>; + apple,iomfb-surfaces = <0x3>; power-domains = <&ps_disp0_cpu0>; resets = <&ps_disp0_cpu0>; clocks = <&clk_disp0>; @@ -1485,6 +1486,7 @@ <0x2 0x3b3d0000 0x0 0x4000>; apple,bw-scratch = <&pmgr_dcp 0 5 0x18>; apple,bw-doorbell = <&pmgr_dcp 1 6>; + apple,iomfb-surfaces = <0x3>; power-domains = <&ps_dispext_cpu0>; resets = <&ps_dispext_cpu0>; clocks = <&clk_dispext0>; diff --git a/arch/arm64/boot/dts/apple/t8112.dtsi b/arch/arm64/boot/dts/apple/t8112.dtsi index b19b94305e47c1..419f9ea8d627cd 100644 --- a/arch/arm64/boot/dts/apple/t8112.dtsi +++ b/arch/arm64/boot/dts/apple/t8112.dtsi @@ -748,6 +748,7 @@ <0x2 0x31344000 0x0 0x4000>, <0x2 0x31800000 0x0 0x800000>; apple,bw-scratch = <&pmgr_dcp 0 4 0x5d8>; + apple,iomfb-surfaces = <0xb>; #ifdef APPLE_USE_PMP power-domains = <&pmp_report_disp0>; #else @@ -1745,6 +1746,7 @@ <0x2 0x71344000 0x0 0x4000>, <0x2 0x71800000 0x0 0x800000>; apple,bw-scratch = <&pmgr_dcp 0 4 0x5e0>; + apple,iomfb-surfaces = <0xb>; #ifdef APPLE_USE_PMP power-domains = <&pmp_report_dispext>; #else diff --git a/drivers/gpu/drm/apple/apple_drv.c b/drivers/gpu/drm/apple/apple_drv.c index 0f36dad6f96351..5324e796c25b33 100644 --- a/drivers/gpu/drm/apple/apple_drv.c +++ b/drivers/gpu/drm/apple/apple_drv.c @@ -272,31 +272,25 @@ static int apple_probe_per_dcp(struct device *dev, struct apple_crtc *crtc; struct apple_connector *connector; struct apple_encoder *enc; - struct drm_plane *planes[DCP_MAX_PLANES]; + struct apple_plane *planes[DCP_MAX_PLANES]; + struct apple_dcp *drv = platform_get_drvdata(dcp); int ret, i; - int immutable_zpos = 0; + int zpos = 0; bool supports_l10r = !dcp_fw_compat_is_12_x(dcp); - planes[0] = apple_plane_init(drm, 1U << num, supports_l10r, - DRM_PLANE_TYPE_PRIMARY); - if (IS_ERR(planes[0])) - return PTR_ERR(planes[0]); - ret = drm_plane_create_zpos_immutable_property(planes[0], immutable_zpos); - if (ret) { - return ret; - } + for (i = 0; i < DCP_MAX_PLANES; i++) { + if (drv->iomfb_surfaces & BIT(i)) { + planes[zpos] = apple_plane_init(drm, 1U << num, supports_l10r, + zpos ? DRM_PLANE_TYPE_OVERLAY : DRM_PLANE_TYPE_PRIMARY); + if (IS_ERR(planes[zpos])) + return PTR_ERR(planes[zpos]); + ret = drm_plane_create_zpos_immutable_property(&planes[zpos]->base, zpos); + if (ret) + return ret; - /* Set up our other planes */ - for (i = 1; i < DCP_MAX_PLANES; i++) { - planes[i] = apple_plane_init(drm, 1U << num, supports_l10r, - DRM_PLANE_TYPE_OVERLAY); - if (IS_ERR(planes[i])) - return PTR_ERR(planes[i]); - immutable_zpos++; - ret = drm_plane_create_zpos_immutable_property(planes[i], immutable_zpos); - if (ret) { - return ret; + planes[zpos]->iomfb_surf = i; + zpos++; } } @@ -307,7 +301,7 @@ static int apple_probe_per_dcp(struct device *dev, * knows what to do with overlays. */ crtc = kzalloc(sizeof(*crtc), GFP_KERNEL); - ret = drm_crtc_init_with_planes(drm, &crtc->base, planes[0], NULL, + ret = drm_crtc_init_with_planes(drm, &crtc->base, &planes[0]->base, NULL, &apple_crtc_funcs, NULL); if (ret) return ret; diff --git a/drivers/gpu/drm/apple/dcp-internal.h b/drivers/gpu/drm/apple/dcp-internal.h index f2eb2483c9a880..2f61a4273a2728 100644 --- a/drivers/gpu/drm/apple/dcp-internal.h +++ b/drivers/gpu/drm/apple/dcp-internal.h @@ -20,7 +20,7 @@ #include "iomfb_v13_3.h" #include "epic/dpavservep.h" -#define DCP_MAX_PLANES 2 +#define DCP_MAX_PLANES 4 struct apple_dcp; struct apple_dcp_afkep; @@ -138,6 +138,8 @@ struct apple_dcp { * sense to keep some of the members in apple_dcp. * **********************************************************************/ + u32 iomfb_surfaces; + /* clock rate request by dcp in */ struct clk *clk; diff --git a/drivers/gpu/drm/apple/dcp.c b/drivers/gpu/drm/apple/dcp.c index 9dfc3fd002f530..7165518fde140d 100644 --- a/drivers/gpu/drm/apple/dcp.c +++ b/drivers/gpu/drm/apple/dcp.c @@ -331,10 +331,7 @@ int dcp_crtc_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state) { struct platform_device *pdev = to_apple_crtc(crtc)->dcp; struct apple_dcp *dcp = platform_get_drvdata(pdev); - struct drm_plane_state *new_state; - struct drm_plane *plane; struct drm_crtc_state *crtc_state; - int plane_idx, plane_count = 0; bool needs_modeset; if (dcp->crashed) @@ -348,19 +345,6 @@ int dcp_crtc_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state) return -EINVAL; } - for_each_new_plane_in_state(state, plane, new_state, plane_idx) { - /* skip planes not for this crtc */ - if (new_state->crtc != crtc) - continue; - - plane_count += 1; - } - - if (plane_count > DCP_MAX_PLANES) { - dev_err(dcp->dev, "crtc_atomic_check: Blend supports only 2 layers!\n"); - return -EINVAL; - } - return 0; } @@ -1237,6 +1221,10 @@ static int dcp_platform_probe(struct platform_device *pdev) if (IS_ERR(dcp->dp2hdmi_pwren)) return PTR_ERR(dcp->dp2hdmi_pwren); + ret = of_property_read_u32(dev->of_node, "apple,iomfb-surfaces", &dcp->iomfb_surfaces); + if (ret) + dcp->iomfb_surfaces = 0b1; + ret = of_property_read_u32(dev->of_node, "mux-index", &mux_index); if (!ret) { dcp->xbar = devm_mux_control_get(dev, "dp-xbar"); diff --git a/drivers/gpu/drm/apple/iomfb.h b/drivers/gpu/drm/apple/iomfb.h index 8a871db0b94a70..7903fad4040677 100644 --- a/drivers/gpu/drm/apple/iomfb.h +++ b/drivers/gpu/drm/apple/iomfb.h @@ -86,8 +86,6 @@ enum iomfb_property_id { /* Structures used in v12.0 firmware */ #define SWAP_SURFACES 4 -/* We have 4 surfaces, but we can only ever blend two */ -#define MAX_BLEND_SURFACES 2 struct dcp_iouserclient { /* Handle for the IOUserClient. macOS sets this to a kernel VA. */ diff --git a/drivers/gpu/drm/apple/iomfb_template.c b/drivers/gpu/drm/apple/iomfb_template.c index 553134aad80c9c..61d8b0c4e8c2b5 100644 --- a/drivers/gpu/drm/apple/iomfb_template.c +++ b/drivers/gpu/drm/apple/iomfb_template.c @@ -1311,26 +1311,13 @@ void DCP_FW_NAME(iomfb_flush)(struct apple_dcp *dcp, struct drm_crtc *crtc, stru for_each_oldnew_plane_in_state(state, plane, old_state, new_state, plane_idx) { struct apple_plane_state *apple_state = to_apple_plane_state(new_state); + struct apple_plane *apl_plane = to_apple_plane(plane); /* skip planes not for this crtc */ if (old_state->crtc != crtc && new_state->crtc != crtc) continue; - /* - * Plane order is nondeterministic for this iterator. DCP will - * almost always crash at some point if the z order of planes - * flip-flops around. Make sure we are always blending them - * in the correct order. - * - * Despite having 4 surfaces, we can only blend two. Surface 0 is - * also unusable on some machines, so ignore it. - */ - - l = MAX_BLEND_SURFACES - new_state->normalized_zpos; - - WARN_ON(l > MAX_BLEND_SURFACES); - - req->swap.swap_enabled |= BIT(l); + req->swap.swap_enabled |= BIT(apl_plane->iomfb_surf); if (old_state->fb && new_state->fb != old_state->fb) { /* @@ -1356,17 +1343,17 @@ void DCP_FW_NAME(iomfb_flush)(struct apple_dcp *dcp, struct drm_crtc *crtc, stru if (!new_state->fb || !new_state->visible) { continue; } - req->surf_null[l] = false; + req->surf_null[apl_plane->iomfb_surf] = false; has_surface = 1; - req->swap.src_rect[l] = apple_state->src_rect; - req->swap.dst_rect[l] = apple_state->dst_rect; + req->swap.src_rect[apl_plane->iomfb_surf] = apple_state->src_rect; + req->swap.dst_rect[apl_plane->iomfb_surf] = apple_state->dst_rect; if (dcp->notch_height > 0) - req->swap.dst_rect[l].y += dcp->notch_height; + req->swap.dst_rect[apl_plane->iomfb_surf].y += dcp->notch_height; - req->surf_iova[l] = apple_state->iova; - req->surf[l].base = apple_state->surf; + req->surf_iova[apl_plane->iomfb_surf] = apple_state->iova; + req->surf[apl_plane->iomfb_surf].base = apple_state->surf; /* Use sRGB colorspace only for internal panels. External * displays are expected to have EDID and user space can use @@ -1374,8 +1361,8 @@ void DCP_FW_NAME(iomfb_flush)(struct apple_dcp *dcp, struct drm_crtc *crtc, stru * colors. */ if (dcp->connector_type == DRM_MODE_CONNECTOR_eDP && - req->surf[l].base.colorspace == DCP_COLORSPACE_BG_SRGB) - req->surf[l].base.colorspace = DCP_COLORSPACE_NATIVE; + req->surf[apl_plane->iomfb_surf].base.colorspace == DCP_COLORSPACE_BG_SRGB) + req->surf[apl_plane->iomfb_surf].base.colorspace = DCP_COLORSPACE_NATIVE; } if (!has_surface && !crtc_state->color_mgmt_changed) { diff --git a/drivers/gpu/drm/apple/plane.c b/drivers/gpu/drm/apple/plane.c index 2f0b76ad84ad65..8654532f4afa30 100644 --- a/drivers/gpu/drm/apple/plane.c +++ b/drivers/gpu/drm/apple/plane.c @@ -430,11 +430,7 @@ u64 apple_format_modifiers[] = { DRM_FORMAT_MOD_INVALID }; -struct apple_plane { - struct drm_plane base; -}; - -struct drm_plane *apple_plane_init(struct drm_device *dev, +struct apple_plane *apple_plane_init(struct drm_device *dev, unsigned long possible_crtcs, bool supports_l10r, enum drm_plane_type type) @@ -487,5 +483,5 @@ struct drm_plane *apple_plane_init(struct drm_device *dev, else drm_plane_helper_add(&plane->base, &apple_plane_helper_funcs); - return &plane->base; + return plane; } diff --git a/drivers/gpu/drm/apple/plane.h b/drivers/gpu/drm/apple/plane.h index 67d15938cf0dcb..c0c28627a61042 100644 --- a/drivers/gpu/drm/apple/plane.h +++ b/drivers/gpu/drm/apple/plane.h @@ -12,6 +12,13 @@ #include "iomfb_plane.h" +struct apple_plane { + struct drm_plane base; + u8 iomfb_surf; +}; + +#define to_apple_plane(x) container_of(x, struct apple_plane, base) + struct apple_plane_state { struct drm_plane_state base; struct dcp_surface surf; @@ -22,7 +29,7 @@ struct apple_plane_state { #define to_apple_plane_state(x) container_of(x, struct apple_plane_state, base) -struct drm_plane *apple_plane_init(struct drm_device *dev, +struct apple_plane *apple_plane_init(struct drm_device *dev, unsigned long possible_crtcs, bool supports_l10r, enum drm_plane_type type);