summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/vkms/vkms_colorop.c
blob: 9424b1994239a67938091449ca87843ff20349eb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// SPDX-License-Identifier: GPL-2.0+

#include <linux/slab.h>
#include <drm/drm_colorop.h>
#include <drm/drm_print.h>
#include <drm/drm_property.h>
#include <drm/drm_plane.h>

#include "vkms_drv.h"

static const u64 supported_tfs =
	BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) |
	BIT(DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF);

static const u64 supported_fm =
	BIT(DRM_COLOROP_FM_YCBCR601_FULL_RGB) |
	BIT(DRM_COLOROP_FM_YCBCR601_LIMITED_RGB) |
	BIT(DRM_COLOROP_FM_YCBCR709_FULL_RGB) |
	BIT(DRM_COLOROP_FM_YCBCR709_LIMITED_RGB) |
	BIT(DRM_COLOROP_FM_YCBCR2020_NC_FULL_RGB) |
	BIT(DRM_COLOROP_FM_YCBCR2020_NC_LIMITED_RGB);

static const struct drm_colorop_funcs vkms_colorop_funcs = {
	.destroy = drm_colorop_destroy,
};

#define MAX_COLOR_PIPELINE_OPS 5

static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list)
{
	struct drm_colorop *ops[MAX_COLOR_PIPELINE_OPS];
	struct drm_device *dev = plane->dev;
	int ret;
	int i = 0, j = 0;

	memset(ops, 0, sizeof(ops));

	/* 1st op: Fixed Matrix (YUV to RGB) */
	ops[i] = kzalloc_obj(*ops[i]);
	if (!ops[i]) {
		drm_err(dev, "KMS: Failed to allocate colorop\n");
		ret = -ENOMEM;
		goto cleanup;
	}

	ret = drm_plane_colorop_fixed_matrix_init(dev, ops[i], plane, &vkms_colorop_funcs,
						  supported_fm,
						  DRM_COLOROP_FLAG_ALLOW_BYPASS);
	if (ret)
		goto cleanup;

	list->type = ops[i]->base.id;

	i++;

	/* 2nd op: 1d curve */
	ops[i] = kzalloc_obj(*ops[i]);
	if (!ops[i]) {
		drm_err(dev, "KMS: Failed to allocate colorop\n");
		ret = -ENOMEM;
		goto cleanup;
	}

	ret = drm_plane_colorop_curve_1d_init(dev, ops[i], plane, &vkms_colorop_funcs,
					      supported_tfs,
					      DRM_COLOROP_FLAG_ALLOW_BYPASS);
	if (ret)
		goto cleanup;

	drm_colorop_set_next_property(ops[i - 1], ops[i]);

	i++;

	/* 3rd op: 3x4 matrix */
	ops[i] = kzalloc_obj(*ops[i]);
	if (!ops[i]) {
		drm_err(dev, "KMS: Failed to allocate colorop\n");
		ret = -ENOMEM;
		goto cleanup;
	}

	ret = drm_plane_colorop_ctm_3x4_init(dev, ops[i], plane, &vkms_colorop_funcs,
					     DRM_COLOROP_FLAG_ALLOW_BYPASS);
	if (ret)
		goto cleanup;

	drm_colorop_set_next_property(ops[i - 1], ops[i]);

	i++;

	/* 4th op: 3x4 matrix */
	ops[i] = kzalloc_obj(*ops[i]);
	if (!ops[i]) {
		drm_err(dev, "KMS: Failed to allocate colorop\n");
		ret = -ENOMEM;
		goto cleanup;
	}

	ret = drm_plane_colorop_ctm_3x4_init(dev, ops[i], plane, &vkms_colorop_funcs,
					     DRM_COLOROP_FLAG_ALLOW_BYPASS);
	if (ret)
		goto cleanup;

	drm_colorop_set_next_property(ops[i - 1], ops[i]);

	i++;

	/* 5th op: 1d curve */
	ops[i] = kzalloc_obj(*ops[i]);
	if (!ops[i]) {
		drm_err(dev, "KMS: Failed to allocate colorop\n");
		ret = -ENOMEM;
		goto cleanup;
	}

	ret = drm_plane_colorop_curve_1d_init(dev, ops[i], plane, &vkms_colorop_funcs,
					      supported_tfs,
					      DRM_COLOROP_FLAG_ALLOW_BYPASS);
	if (ret)
		goto cleanup;

	drm_colorop_set_next_property(ops[i - 1], ops[i]);

	list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", ops[0]->base.id);

	return 0;

cleanup:
	for (j = 0; j < i; j++) {
		if (ops[j]) {
			drm_colorop_cleanup(ops[j]);
			kfree(ops[j]);
		}
	}

	return ret;
}

int vkms_initialize_colorops(struct drm_plane *plane)
{
	struct drm_prop_enum_list pipeline = {};
	int ret = 0;

	/* Add color pipeline */
	ret = vkms_initialize_color_pipeline(plane, &pipeline);
	if (ret)
		goto out;

	/* Create COLOR_PIPELINE property and attach */
	ret = drm_plane_create_color_pipeline_property(plane, &pipeline, 1);

	kfree(pipeline.name);
out:
	return ret;
}