diff --git a/.github/workflows/kernel-build.yml b/.github/workflows/kernel-build.yml index 1d879fb53712cd..8caa1da0324baa 100644 --- a/.github/workflows/kernel-build.yml +++ b/.github/workflows/kernel-build.yml @@ -67,7 +67,7 @@ jobs: else sudo apt-get install gcc-arm-linux-gnueabihf; fi - timeout-minutes: 5 + timeout-minutes: 10 - uses: actions/checkout@v4 with: diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index c7ff2123780650..d7ae49d332ffa9 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -74,6 +74,7 @@ __drm_atomic_helper_crtc_state_reset(struct drm_crtc_state *crtc_state, struct drm_crtc *crtc) { crtc_state->crtc = crtc; + crtc_state->background_color = drm_argb64(0xffff, 0, 0, 0); } EXPORT_SYMBOL(__drm_atomic_helper_crtc_state_reset); diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 4f8bf87c1949de..b5025cc66f8004 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -405,6 +405,8 @@ static int drm_atomic_crtc_set_property(struct drm_crtc *crtc, &replaced); state->color_mgmt_changed |= replaced; return ret; + } else if (property == config->background_color_property) { + state->background_color = val; } else if (property == config->prop_out_fence_ptr) { s32 __user *fence_ptr = u64_to_user_ptr(val); @@ -450,6 +452,8 @@ drm_atomic_crtc_get_property(struct drm_crtc *crtc, *val = (state->ctm) ? state->ctm->base.id : 0; else if (property == config->gamma_lut_property) *val = (state->gamma_lut) ? state->gamma_lut->base.id : 0; + else if (property == config->background_color_property) + *val = state->background_color; else if (property == config->prop_out_fence_ptr) *val = 0; else if (property == crtc->scaling_filter_property) diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c index 4e63000713dbfd..70077e1034ba51 100644 --- a/drivers/gpu/drm/drm_blend.c +++ b/drivers/gpu/drm/drm_blend.c @@ -185,10 +185,6 @@ * plane does not expose the "alpha" property, then this is * assumed to be 1.0 * - * Note that all the property extensions described here apply either to the - * plane or the CRTC (e.g. for the background color, which currently is not - * exposed and assumed to be black). - * * SCALING_FILTER: * Indicates scaling filter to be used for plane scaler * @@ -201,6 +197,23 @@ * * Drivers can set up this property for a plane by calling * drm_plane_create_scaling_filter_property + * + * The property extensions described above all apply to the plane. Drivers + * may also expose the following crtc property extension: + * + * BACKGROUND_COLOR: + * Background color is set via drm_crtc_attach_background_color_property(). + * It controls the ARGB color of a full-screen layer that exists below all + * planes. This color will be used for pixels not covered by any plane and + * may also be blended with plane contents as allowed by a plane's alpha + * values. The background color defaults to black, and is assumed to be + * black for drivers that do not expose this property. Although background + * color isn't a plane, it is assumed that the color provided here + * undergoes the same pipe-level degamma/CSC/gamma transformations that + * planes undergo. Note that the color value provided here includes an + * alpha channel, hence non-opaque background color values are allowed, but + * are generally only honored in special cases (e.g. when a memory + * writeback connector is in use). */ /** @@ -648,3 +661,19 @@ int drm_plane_create_blend_mode_property(struct drm_plane *plane, return 0; } EXPORT_SYMBOL(drm_plane_create_blend_mode_property); + +/** + * drm_crtc_attach_background_color_property - attach background color property + * @crtc: drm crtc + * + * Attaches the background color property to @crtc. The property defaults to + * solid black and will accept 64-bit ARGB values in the format generated by + * drm_argb64(). + */ +void drm_crtc_attach_background_color_property(struct drm_crtc *crtc) +{ + drm_object_attach_property(&crtc->base, + crtc->dev->mode_config.background_color_property, + drm_argb64(0xffff, 0, 0, 0)); +} +EXPORT_SYMBOL(drm_crtc_attach_background_color_property); diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c index fdc44fd1c56d41..1a6c4c7395193d 100644 --- a/drivers/gpu/drm/drm_mode_config.c +++ b/drivers/gpu/drm/drm_mode_config.c @@ -365,6 +365,12 @@ static int drm_mode_create_standard_properties(struct drm_device *dev) return -ENOMEM; dev->mode_config.gamma_lut_size_property = prop; + prop = drm_property_create_range(dev, 0, + "BACKGROUND_COLOR", 0, U64_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.background_color_property = prop; + prop = drm_property_create(dev, DRM_MODE_PROP_IMMUTABLE | DRM_MODE_PROP_BLOB, "IN_FORMATS", 0); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 5d7df4c3b08c47..bc6582f1193a69 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -1544,6 +1544,7 @@ static void vop2_post_config(struct drm_crtc *crtc) { struct vop2_video_port *vp = to_vop2_video_port(crtc); struct drm_display_mode *mode = &crtc->state->adjusted_mode; + u64 bgcolor = crtc->state->background_color; u16 vtotal = mode->crtc_vtotal; u16 hdisplay = mode->crtc_hdisplay; u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; @@ -1597,7 +1598,11 @@ static void vop2_post_config(struct drm_crtc *crtc) vop2_vp_write(vp, RK3568_VP_POST_DSP_VACT_INFO_F1, val); } - vop2_vp_write(vp, RK3568_VP_DSP_BG, 0); + /* Background color is programmed with 10 bits of precision */ + val = FIELD_PREP(RK3568_VP_DSP_BG__DSP_BG_RED, DRM_ARGB64_RED(bgcolor)); + val |= FIELD_PREP(RK3568_VP_DSP_BG__DSP_BG_GREEN, DRM_ARGB64_GREEN(bgcolor)); + val |= FIELD_PREP(RK3568_VP_DSP_BG__DSP_BG_BLUE, DRM_ARGB64_BLUE(bgcolor)); + vop2_vp_write(vp, RK3568_VP_DSP_BG, val); } static unsigned long rk3568_set_intf_mux(struct vop2_video_port *vp, int id, u32 polflags) @@ -2884,6 +2889,8 @@ static int vop2_create_crtcs(struct vop2 *vop2) return ret; } + drm_crtc_attach_background_color_property(&vp->crtc); + drm_crtc_helper_add(&vp->crtc, &vop2_crtc_helper_funcs); init_completion(&vp->dsp_hold_completion); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h index 130aaa40316d13..45edf1fc72c711 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h @@ -421,6 +421,10 @@ enum dst_factor_mode { #define RK3588_VP_CLK_CTRL__DCLK_OUT_DIV GENMASK(3, 2) #define RK3588_VP_CLK_CTRL__DCLK_CORE_DIV GENMASK(1, 0) +#define RK3568_VP_DSP_BG__DSP_BG_RED GENMASK(29, 20) +#define RK3568_VP_DSP_BG__DSP_BG_GREEN GENMASK(19, 10) +#define RK3568_VP_DSP_BG__DSP_BG_BLUE GENMASK(9, 0) + #define RK3568_VP_POST_SCL_CTRL__VSCALEDOWN BIT(1) #define RK3568_VP_POST_SCL_CTRL__HSCALEDOWN BIT(0) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 307a533136692c..8a3eb29ef10de1 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -1437,6 +1438,8 @@ int __vc4_crtc_init(struct drm_device *drm, if (ret) return ret; + drm_crtc_attach_background_color_property(crtc); + drm_crtc_helper_add(crtc, crtc_helper_funcs); if (vc4->gen == VC4_GEN_4) { diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c index 73680550bcef74..b2146a71a21e8c 100644 --- a/drivers/gpu/drm/vc4/vc4_hvs.c +++ b/drivers/gpu/drm/vc4/vc4_hvs.c @@ -1256,6 +1256,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc, struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); unsigned int channel = vc4_state->assigned_channel; + u64 bgcolor = crtc->state->background_color; struct drm_plane *plane; struct vc4_plane_state *vc4_plane_state; bool debug_dump_regs = false; @@ -1320,16 +1321,32 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc, WARN_ON_ONCE(dlist_next - dlist_start != vc4_state->mm->mm_node.size); if (vc4->gen >= VC4_GEN_6_C) { - /* This sets a black background color fill, as is the case + /* This sets the background color fill, as is the case * with other DRM drivers. */ + if (vc4->gen == VC4_GEN_6_C) { + HVS_WRITE(SCALER6_DISPX_BGND(channel), + ((bgcolor & 0xFF0000000000) >> 24) | + ((bgcolor & 0xFF000000) >> 16) | + ((bgcolor & 0xFF00) >> 8)); + } else { + /* GEN_6_D takes a 12bit background colour */ + HVS_WRITE(SCALER6D_DISPX_BGND0(channel), + bgcolor & 0xFFF0FFF0); + HVS_WRITE(SCALER6D_DISPX_BGND1(channel), + (bgcolor >> 32) & 0xFFF0); + } hvs->bg_fill[channel] = enable_bg_fill; } else { /* we can actually run with a lower core clock when background * fill is enabled on VC4_GEN_5 so leave it enabled always. */ HVS_WRITE(SCALER_DISPBKGNDX(channel), - HVS_READ(SCALER_DISPBKGNDX(channel)) | + (HVS_READ(SCALER_DISPBKGNDX(channel)) & + ~SCALER_DISPBKGND_FILL_COLOUR) | + ((bgcolor & 0xFF0000000000) >> 24) | + ((bgcolor & 0xFF000000) >> 16) | + ((bgcolor & 0xFF00) >> 8) | SCALER_DISPBKGND_FILL); } diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h index 68d83d27c32ad9..afd3eda5aaf413 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h @@ -402,6 +402,7 @@ * opaque display planes will cover everything. */ # define SCALER_DISPBKGND_FILL BIT(24) +# define SCALER_DISPBKGND_FILL_COLOUR VC4_MASK(23, 0) #define SCALER_DISPSTAT0 0x00000048 # define SCALER_DISPSTATX_MODE_MASK VC4_MASK(31, 30) @@ -580,9 +581,8 @@ # define SCALER6_DISPX_CTRL1_INTLACE BIT(0) #define SCALER6_DISP0_BGND 0x00000038 -#define SCALER6_DISPX_BGND(x) ((hvs->vc4->gen == VC4_GEN_6_C) ? \ - (SCALER6_DISP0_BGND + ((x) * (SCALER6_DISP1_BGND - SCALER6_DISP0_BGND))) : \ - (SCALER6D_DISP0_BGND + ((x) * (SCALER6D_DISP1_BGND - SCALER6D_DISP0_BGND)))) +#define SCALER6_DISPX_BGND(x) \ + (SCALER6_DISP0_BGND + ((x) * (SCALER6_DISP1_BGND - SCALER6_DISP0_BGND))) #define SCALER6_DISP0_LPTRS 0x0000003c #define SCALER6_DISPX_LPTRS(x) ((hvs->vc4->gen == VC4_GEN_6_C) ? \ @@ -698,16 +698,14 @@ #define SCALER6D_HISTBIN7 0x000000f0 #define SCALER6D_HVS_ID 0x000000fc -#define SCALER6D_DISP0_CTRL0 0x00000100 -#define SCALER6D_DISP0_CTRL1 0x00000104 -#define SCALER6D_DISP0_BGND 0x00000108 -#define SCALER6D_DISP0_LPTRS 0x00000110 -#define SCALER6D_DISP0_COB 0x00000114 -#define SCALER6D_DISP0_STATUS 0x00000118 #define SCALER6D_DISP0_CTRL0 0x00000100 #define SCALER6D_DISP0_CTRL1 0x00000104 #define SCALER6D_DISP0_BGND0 0x00000108 +#define SCALER6D_DISPX_BGND0(x) \ + (SCALER6D_DISP0_BGND0 + ((x) * (SCALER6D_DISP1_BGND0 - SCALER6D_DISP0_BGND0))) #define SCALER6D_DISP0_BGND1 0x0000010c +#define SCALER6D_DISPX_BGND1(x) \ + (SCALER6D_DISP0_BGND1 + ((x) * (SCALER6D_DISP1_BGND1 - SCALER6D_DISP0_BGND1))) #define SCALER6D_DISP0_LPTRS 0x00000110 #define SCALER6D_DISP0_COB 0x00000114 #define SCALER6D_DISP0_STATUS 0x00000118 diff --git a/include/drm/drm_blend.h b/include/drm/drm_blend.h index a84c58f3f13cdc..2599c27e09c3d3 100644 --- a/include/drm/drm_blend.h +++ b/include/drm/drm_blend.h @@ -31,8 +31,9 @@ #define DRM_MODE_BLEND_COVERAGE 1 #define DRM_MODE_BLEND_PIXEL_NONE 2 -struct drm_device; struct drm_atomic_state; +struct drm_crtc; +struct drm_device; struct drm_plane; struct drm_connector; @@ -59,7 +60,7 @@ int drm_atomic_normalize_zpos(struct drm_device *dev, struct drm_atomic_state *state); int drm_plane_create_blend_mode_property(struct drm_plane *plane, unsigned int supported_modes); - +void drm_crtc_attach_background_color_property(struct drm_crtc *crtc); int drm_connector_create_rotation_property(struct drm_connector *conn, unsigned int rotation, unsigned int supported_rotations); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index dd7ad1a44717e8..a092c9c4550d6a 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -274,6 +274,18 @@ struct drm_crtc_state { */ struct drm_property_blob *gamma_lut; + /** + * @background_color: + * + * RGB value representing the pipe's background color. The background + * color (aka "canvas color") of a pipe is the color that will be used + * for pixels not covered by a plane, or covered by transparent pixels + * of a plane. The value here should be built using drm_argb64(), while + * the individual color components can be extracted with desired + * precision via the DRM_ARGB64_*() macros. + */ + u64 background_color; + /** * @target_vblank: * diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index 271765e2e9f2da..735f3a5eb73aa2 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -813,6 +813,11 @@ struct drm_mode_config { * gamma LUT as supported by the driver (read-only). */ struct drm_property *gamma_lut_size_property; + /** + * @background_color_property: Optional CRTC property to set the + * background color. + */ + struct drm_property *background_color_property; /** * @suggested_x_property: Optional connector property with a hint for diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 563e337d55a508..5a81c9f14271cc 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -1356,6 +1356,36 @@ struct drm_mode_closefb { __u32 pad; }; +/* + * Put 16-bit ARGB values into a standard 64-bit representation that + * can be used for ioctl parameters, inter-driver communication, etc. + */ +static inline __u64 +drm_argb64(__u16 alpha, __u16 red, __u16 green, __u16 blue) +{ + return (__u64)alpha << 48 | (__u64)red << 32 | (__u64)green << 16 | blue; +} + +/* + * Extract the specified number of least-significant bits of a specific + * color component from a standard 64-bit ARGB value. + */ +#define DRM_ARGB64_COMP(c, shift, numlsb) \ + ((__u16)(((c) >> (shift)) & ((1UL << (numlsb) % 17) - 1))) +#define DRM_ARGB64_ALPHA_LSB(c, numlsb) DRM_ARGB64_COMP(c, 48, numlsb) +#define DRM_ARGB64_RED_LSB(c, numlsb) DRM_ARGB64_COMP(c, 32, numlsb) +#define DRM_ARGB64_GREEN_LSB(c, numlsb) DRM_ARGB64_COMP(c, 16, numlsb) +#define DRM_ARGB64_BLUE_LSB(c, numlsb) DRM_ARGB64_COMP(c, 0, numlsb) + +/* + * Convenience wrappers to extract all 16 bits of a specific color + * component from a standard 64-bit ARGB value. + */ +#define DRM_ARGB64_ALPHA(c) DRM_ARGB64_ALPHA_LSB(c, 16) +#define DRM_ARGB64_RED(c) DRM_ARGB64_RED_LSB(c, 16) +#define DRM_ARGB64_GREEN(c) DRM_ARGB64_GREEN_LSB(c, 16) +#define DRM_ARGB64_BLUE(c) DRM_ARGB64_BLUE_LSB(c, 16) + #if defined(__cplusplus) } #endif