Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/plane: Add COLOR PIPELINE property

We're adding a new enum COLOR PIPELINE property. This
property will have entries for each COLOR PIPELINE by
referencing the DRM object ID of the first drm_colorop
of the pipeline. 0 disables the entire COLOR PIPELINE.

Userspace can use this to discover the available color
pipelines, as well as set the desired one. The color
pipelines are programmed via properties on the actual
drm_colorop objects.

Reviewed-by: Simon Ser <contact@emersion.fr>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Daniel Stone <daniels@collabora.com>
Reviewed-by: Melissa Wen <mwen@igalia.com>
Reviewed-by: Sebastian Wick <sebastian.wick@redhat.com>
Signed-off-by: Simon Ser <contact@emersion.fr>
Link: https://patch.msgid.link/20251115000237.3561250-11-alex.hung@amd.com

authored by

Harry Wentland and committed by
Simon Ser
2afc3184 2190c144

+166
+46
drivers/gpu/drm/drm_atomic.c
··· 1537 1537 EXPORT_SYMBOL(drm_atomic_add_affected_planes); 1538 1538 1539 1539 /** 1540 + * drm_atomic_add_affected_colorops - add colorops for plane 1541 + * @state: atomic state 1542 + * @plane: DRM plane 1543 + * 1544 + * This function walks the current configuration and adds all colorops 1545 + * currently used by @plane to the atomic configuration @state. This is useful 1546 + * when an atomic commit also needs to check all currently enabled colorop on 1547 + * @plane, e.g. when changing the mode. It's also useful when re-enabling a plane 1548 + * to avoid special code to force-enable all colorops. 1549 + * 1550 + * Since acquiring a colorop state will always also acquire the w/w mutex of the 1551 + * current plane for that colorop (if there is any) adding all the colorop states for 1552 + * a plane will not reduce parallelism of atomic updates. 1553 + * 1554 + * Returns: 1555 + * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK 1556 + * then the w/w mutex code has detected a deadlock and the entire atomic 1557 + * sequence must be restarted. All other errors are fatal. 1558 + */ 1559 + int 1560 + drm_atomic_add_affected_colorops(struct drm_atomic_state *state, 1561 + struct drm_plane *plane) 1562 + { 1563 + struct drm_colorop *colorop; 1564 + struct drm_colorop_state *colorop_state; 1565 + 1566 + WARN_ON(!drm_atomic_get_new_plane_state(state, plane)); 1567 + 1568 + drm_dbg_atomic(plane->dev, 1569 + "Adding all current colorops for [PLANE:%d:%s] to %p\n", 1570 + plane->base.id, plane->name, state); 1571 + 1572 + drm_for_each_colorop(colorop, plane->dev) { 1573 + if (colorop->plane != plane) 1574 + continue; 1575 + 1576 + colorop_state = drm_atomic_get_colorop_state(state, colorop); 1577 + if (IS_ERR(colorop_state)) 1578 + return PTR_ERR(colorop_state); 1579 + } 1580 + 1581 + return 0; 1582 + } 1583 + EXPORT_SYMBOL(drm_atomic_add_affected_colorops); 1584 + 1585 + /** 1540 1586 * drm_atomic_check_only - check whether a given config would work 1541 1587 * @state: atomic configuration to check 1542 1588 *
+5
drivers/gpu/drm/drm_atomic_state_helper.c
··· 268 268 plane_state->color_range = val; 269 269 } 270 270 271 + if (plane->color_pipeline_property) { 272 + /* default is always NULL, i.e., bypass */ 273 + plane_state->color_pipeline = NULL; 274 + } 275 + 271 276 if (plane->zpos_property) { 272 277 if (!drm_object_property_get_default_value(&plane->base, 273 278 plane->zpos_property,
+40
drivers/gpu/drm/drm_atomic_uapi.c
··· 259 259 EXPORT_SYMBOL(drm_atomic_set_fb_for_plane); 260 260 261 261 /** 262 + * drm_atomic_set_colorop_for_plane - set colorop for plane 263 + * @plane_state: atomic state object for the plane 264 + * @colorop: colorop to use for the plane 265 + * 266 + * Helper function to select the color pipeline on a plane by setting 267 + * it to the first drm_colorop element of the pipeline. 268 + */ 269 + void 270 + drm_atomic_set_colorop_for_plane(struct drm_plane_state *plane_state, 271 + struct drm_colorop *colorop) 272 + { 273 + struct drm_plane *plane = plane_state->plane; 274 + 275 + if (colorop) 276 + drm_dbg_atomic(plane->dev, 277 + "Set [COLOROP:%d] for [PLANE:%d:%s] state %p\n", 278 + colorop->base.id, plane->base.id, plane->name, 279 + plane_state); 280 + else 281 + drm_dbg_atomic(plane->dev, 282 + "Set [NOCOLOROP] for [PLANE:%d:%s] state %p\n", 283 + plane->base.id, plane->name, plane_state); 284 + 285 + plane_state->color_pipeline = colorop; 286 + } 287 + EXPORT_SYMBOL(drm_atomic_set_colorop_for_plane); 288 + 289 + /** 262 290 * drm_atomic_set_crtc_for_connector - set CRTC for connector 263 291 * @conn_state: atomic state object for the connector 264 292 * @crtc: CRTC to use for the connector ··· 573 545 state->color_encoding = val; 574 546 } else if (property == plane->color_range_property) { 575 547 state->color_range = val; 548 + } else if (property == plane->color_pipeline_property) { 549 + /* find DRM colorop object */ 550 + struct drm_colorop *colorop = NULL; 551 + 552 + colorop = drm_colorop_find(dev, file_priv, val); 553 + 554 + if (val && !colorop) 555 + return -EACCES; 556 + 557 + drm_atomic_set_colorop_for_plane(state, colorop); 576 558 } else if (property == config->prop_fb_damage_clips) { 577 559 ret = drm_property_replace_blob_from_id(dev, 578 560 &state->fb_damage_clips, ··· 665 627 *val = state->color_encoding; 666 628 } else if (property == plane->color_range_property) { 667 629 *val = state->color_range; 630 + } else if (property == plane->color_pipeline_property) { 631 + *val = (state->color_pipeline) ? state->color_pipeline->base.id : 0; 668 632 } else if (property == config->prop_fb_damage_clips) { 669 633 *val = (state->fb_damage_clips) ? 670 634 state->fb_damage_clips->base.id : 0;
+59
drivers/gpu/drm/drm_plane.c
··· 1820 1820 return 0; 1821 1821 } 1822 1822 EXPORT_SYMBOL(drm_plane_add_size_hints_property); 1823 + 1824 + /** 1825 + * drm_plane_create_color_pipeline_property - create a new color pipeline 1826 + * property 1827 + * 1828 + * @plane: drm plane 1829 + * @pipelines: list of pipelines 1830 + * @num_pipelines: number of pipelines 1831 + * 1832 + * Create the COLOR_PIPELINE plane property to specific color pipelines on 1833 + * the plane. 1834 + * 1835 + * RETURNS: 1836 + * Zero for success or -errno 1837 + */ 1838 + int drm_plane_create_color_pipeline_property(struct drm_plane *plane, 1839 + const struct drm_prop_enum_list *pipelines, 1840 + int num_pipelines) 1841 + { 1842 + struct drm_prop_enum_list *all_pipelines; 1843 + struct drm_property *prop; 1844 + int len = 0; 1845 + int i; 1846 + 1847 + all_pipelines = kcalloc(num_pipelines + 1, 1848 + sizeof(*all_pipelines), 1849 + GFP_KERNEL); 1850 + 1851 + if (!all_pipelines) { 1852 + drm_err(plane->dev, "failed to allocate color pipeline\n"); 1853 + return -ENOMEM; 1854 + } 1855 + 1856 + /* Create default Bypass color pipeline */ 1857 + all_pipelines[len].type = 0; 1858 + all_pipelines[len].name = "Bypass"; 1859 + len++; 1860 + 1861 + /* Add all other color pipelines */ 1862 + for (i = 0; i < num_pipelines; i++, len++) { 1863 + all_pipelines[len].type = pipelines[i].type; 1864 + all_pipelines[len].name = pipelines[i].name; 1865 + } 1866 + 1867 + prop = drm_property_create_enum(plane->dev, DRM_MODE_PROP_ATOMIC, 1868 + "COLOR_PIPELINE", 1869 + all_pipelines, len); 1870 + if (IS_ERR(prop)) { 1871 + kfree(all_pipelines); 1872 + return PTR_ERR(prop); 1873 + } 1874 + 1875 + drm_object_attach_property(&plane->base, prop, 0); 1876 + plane->color_pipeline_property = prop; 1877 + 1878 + kfree(all_pipelines); 1879 + return 0; 1880 + } 1881 + EXPORT_SYMBOL(drm_plane_create_color_pipeline_property);
+3
include/drm/drm_atomic.h
··· 906 906 int __must_check 907 907 drm_atomic_add_affected_planes(struct drm_atomic_state *state, 908 908 struct drm_crtc *crtc); 909 + int __must_check 910 + drm_atomic_add_affected_colorops(struct drm_atomic_state *state, 911 + struct drm_plane *plane); 909 912 910 913 int __must_check drm_atomic_check_only(struct drm_atomic_state *state); 911 914 int __must_check drm_atomic_commit(struct drm_atomic_state *state);
+2
include/drm/drm_atomic_uapi.h
··· 50 50 struct drm_crtc *crtc); 51 51 void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state, 52 52 struct drm_framebuffer *fb); 53 + void drm_atomic_set_colorop_for_plane(struct drm_plane_state *plane_state, 54 + struct drm_colorop *colorop); 53 55 int __must_check 54 56 drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state, 55 57 struct drm_crtc *crtc);
+11
include/drm/drm_plane.h
··· 792 792 struct drm_property *color_range_property; 793 793 794 794 /** 795 + * @color_pipeline_property: 796 + * 797 + * Optional "COLOR_PIPELINE" enum property for specifying 798 + * a color pipeline to use on the plane. 799 + */ 800 + struct drm_property *color_pipeline_property; 801 + 802 + /** 795 803 * @scaling_filter_property: property to apply a particular filter while 796 804 * scaling. 797 805 */ ··· 1022 1014 const struct drm_plane_size_hint *hints, 1023 1015 int num_hints); 1024 1016 1017 + int drm_plane_create_color_pipeline_property(struct drm_plane *plane, 1018 + const struct drm_prop_enum_list *pipelines, 1019 + int num_pipelines); 1025 1020 #endif