xref: /linux/drivers/gpu/drm/vkms/vkms_colorop.c (revision bf4afc53b77aeaa48b5409da5c8da6bb4eff7f43)
1 // SPDX-License-Identifier: GPL-2.0+
2 
3 #include <linux/slab.h>
4 #include <drm/drm_colorop.h>
5 #include <drm/drm_print.h>
6 #include <drm/drm_property.h>
7 #include <drm/drm_plane.h>
8 
9 #include "vkms_drv.h"
10 
11 static const u64 supported_tfs =
12 	BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) |
13 	BIT(DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF);
14 
15 #define MAX_COLOR_PIPELINE_OPS 4
16 
vkms_initialize_color_pipeline(struct drm_plane * plane,struct drm_prop_enum_list * list)17 static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list)
18 {
19 	struct drm_colorop *ops[MAX_COLOR_PIPELINE_OPS];
20 	struct drm_device *dev = plane->dev;
21 	int ret;
22 	int i = 0, j = 0;
23 
24 	memset(ops, 0, sizeof(ops));
25 
26 	/* 1st op: 1d curve */
27 	ops[i] = kzalloc_obj(*ops[i]);
28 	if (!ops[i]) {
29 		drm_err(dev, "KMS: Failed to allocate colorop\n");
30 		ret = -ENOMEM;
31 		goto cleanup;
32 	}
33 
34 	ret = drm_plane_colorop_curve_1d_init(dev, ops[i], plane, supported_tfs,
35 					      DRM_COLOROP_FLAG_ALLOW_BYPASS);
36 	if (ret)
37 		goto cleanup;
38 
39 	list->type = ops[i]->base.id;
40 
41 	i++;
42 
43 	/* 2nd op: 3x4 matrix */
44 	ops[i] = kzalloc_obj(*ops[i]);
45 	if (!ops[i]) {
46 		drm_err(dev, "KMS: Failed to allocate colorop\n");
47 		ret = -ENOMEM;
48 		goto cleanup;
49 	}
50 
51 	ret = drm_plane_colorop_ctm_3x4_init(dev, ops[i], plane, DRM_COLOROP_FLAG_ALLOW_BYPASS);
52 	if (ret)
53 		goto cleanup;
54 
55 	drm_colorop_set_next_property(ops[i - 1], ops[i]);
56 
57 	i++;
58 
59 	/* 3rd op: 3x4 matrix */
60 	ops[i] = kzalloc_obj(*ops[i]);
61 	if (!ops[i]) {
62 		drm_err(dev, "KMS: Failed to allocate colorop\n");
63 		ret = -ENOMEM;
64 		goto cleanup;
65 	}
66 
67 	ret = drm_plane_colorop_ctm_3x4_init(dev, ops[i], plane, DRM_COLOROP_FLAG_ALLOW_BYPASS);
68 	if (ret)
69 		goto cleanup;
70 
71 	drm_colorop_set_next_property(ops[i - 1], ops[i]);
72 
73 	i++;
74 
75 	/* 4th op: 1d curve */
76 	ops[i] = kzalloc_obj(*ops[i]);
77 	if (!ops[i]) {
78 		drm_err(dev, "KMS: Failed to allocate colorop\n");
79 		ret = -ENOMEM;
80 		goto cleanup;
81 	}
82 
83 	ret = drm_plane_colorop_curve_1d_init(dev, ops[i], plane, supported_tfs,
84 					      DRM_COLOROP_FLAG_ALLOW_BYPASS);
85 	if (ret)
86 		goto cleanup;
87 
88 	drm_colorop_set_next_property(ops[i - 1], ops[i]);
89 
90 	list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", ops[0]->base.id);
91 
92 	return 0;
93 
94 cleanup:
95 	for (j = 0; j < i; j++) {
96 		if (ops[j]) {
97 			drm_colorop_cleanup(ops[j]);
98 			kfree(ops[j]);
99 		}
100 	}
101 
102 	return ret;
103 }
104 
vkms_initialize_colorops(struct drm_plane * plane)105 int vkms_initialize_colorops(struct drm_plane *plane)
106 {
107 	struct drm_prop_enum_list pipeline = {};
108 	int ret = 0;
109 
110 	/* Add color pipeline */
111 	ret = vkms_initialize_color_pipeline(plane, &pipeline);
112 	if (ret)
113 		goto out;
114 
115 	/* Create COLOR_PIPELINE property and attach */
116 	ret = drm_plane_create_color_pipeline_property(plane, &pipeline, 1);
117 
118 	kfree(pipeline.name);
119 out:
120 	return ret;
121 }
122