1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (c) 2014 The Linux Foundation. All rights reserved. |
4 | * Copyright (C) 2013 Red Hat |
5 | * Author: Rob Clark <robdclark@gmail.com> |
6 | */ |
7 | |
8 | #include <drm/drm_fourcc.h> |
9 | #include <drm/drm_framebuffer.h> |
10 | |
11 | #include "msm_drv.h" |
12 | #include "mdp_kms.h" |
13 | |
14 | static struct csc_cfg csc_convert[CSC_MAX] = { |
15 | [CSC_RGB2RGB] = { |
16 | .type = CSC_RGB2RGB, |
17 | .matrix = { |
18 | 0x0200, 0x0000, 0x0000, |
19 | 0x0000, 0x0200, 0x0000, |
20 | 0x0000, 0x0000, 0x0200 |
21 | }, |
22 | .pre_bias = { 0x0, 0x0, 0x0 }, |
23 | .post_bias = { 0x0, 0x0, 0x0 }, |
24 | .pre_clamp = { 0x0, 0xff, 0x0, 0xff, 0x0, 0xff }, |
25 | .post_clamp = { 0x0, 0xff, 0x0, 0xff, 0x0, 0xff }, |
26 | }, |
27 | [CSC_YUV2RGB] = { |
28 | .type = CSC_YUV2RGB, |
29 | .matrix = { |
30 | 0x0254, 0x0000, 0x0331, |
31 | 0x0254, 0xff37, 0xfe60, |
32 | 0x0254, 0x0409, 0x0000 |
33 | }, |
34 | .pre_bias = { 0xfff0, 0xff80, 0xff80 }, |
35 | .post_bias = { 0x00, 0x00, 0x00 }, |
36 | .pre_clamp = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff }, |
37 | .post_clamp = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff }, |
38 | }, |
39 | [CSC_RGB2YUV] = { |
40 | .type = CSC_RGB2YUV, |
41 | .matrix = { |
42 | 0x0083, 0x0102, 0x0032, |
43 | 0x1fb5, 0x1f6c, 0x00e1, |
44 | 0x00e1, 0x1f45, 0x1fdc |
45 | }, |
46 | .pre_bias = { 0x00, 0x00, 0x00 }, |
47 | .post_bias = { 0x10, 0x80, 0x80 }, |
48 | .pre_clamp = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff }, |
49 | .post_clamp = { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0 }, |
50 | }, |
51 | [CSC_YUV2YUV] = { |
52 | .type = CSC_YUV2YUV, |
53 | .matrix = { |
54 | 0x0200, 0x0000, 0x0000, |
55 | 0x0000, 0x0200, 0x0000, |
56 | 0x0000, 0x0000, 0x0200 |
57 | }, |
58 | .pre_bias = { 0x00, 0x00, 0x00 }, |
59 | .post_bias = { 0x00, 0x00, 0x00 }, |
60 | .pre_clamp = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff }, |
61 | .post_clamp = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff }, |
62 | }, |
63 | }; |
64 | |
65 | #define FMT(name, a, r, g, b, e0, e1, e2, e3, alpha, tight, c, cnt, fp, cs, yuv) { \ |
66 | .base = { .pixel_format = DRM_FORMAT_ ## name }, \ |
67 | .bpc_a = BPC ## a ## A, \ |
68 | .bpc_r = BPC ## r, \ |
69 | .bpc_g = BPC ## g, \ |
70 | .bpc_b = BPC ## b, \ |
71 | .unpack = { e0, e1, e2, e3 }, \ |
72 | .alpha_enable = alpha, \ |
73 | .unpack_tight = tight, \ |
74 | .cpp = c, \ |
75 | .unpack_count = cnt, \ |
76 | .fetch_type = fp, \ |
77 | .chroma_sample = cs, \ |
78 | .is_yuv = yuv, \ |
79 | } |
80 | |
81 | #define BPC0A 0 |
82 | |
83 | /* |
84 | * Note: Keep RGB formats 1st, followed by YUV formats to avoid breaking |
85 | * mdp_get_rgb_formats()'s implementation. |
86 | */ |
87 | static const struct mdp_format formats[] = { |
88 | /* name a r g b e0 e1 e2 e3 alpha tight cpp cnt ... */ |
89 | FMT(ARGB8888, 8, 8, 8, 8, 1, 0, 2, 3, true, true, 4, 4, |
90 | MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), |
91 | FMT(ABGR8888, 8, 8, 8, 8, 2, 0, 1, 3, true, true, 4, 4, |
92 | MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), |
93 | FMT(RGBA8888, 8, 8, 8, 8, 3, 1, 0, 2, true, true, 4, 4, |
94 | MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), |
95 | FMT(BGRA8888, 8, 8, 8, 8, 3, 2, 0, 1, true, true, 4, 4, |
96 | MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), |
97 | FMT(XRGB8888, 8, 8, 8, 8, 1, 0, 2, 3, false, true, 4, 4, |
98 | MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), |
99 | FMT(XBGR8888, 8, 8, 8, 8, 2, 0, 1, 3, false, true, 4, 4, |
100 | MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), |
101 | FMT(RGBX8888, 8, 8, 8, 8, 3, 1, 0, 2, false, true, 4, 4, |
102 | MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), |
103 | FMT(BGRX8888, 8, 8, 8, 8, 3, 2, 0, 1, false, true, 4, 4, |
104 | MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), |
105 | FMT(RGB888, 0, 8, 8, 8, 1, 0, 2, 0, false, true, 3, 3, |
106 | MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), |
107 | FMT(BGR888, 0, 8, 8, 8, 2, 0, 1, 0, false, true, 3, 3, |
108 | MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), |
109 | FMT(RGB565, 0, 5, 6, 5, 1, 0, 2, 0, false, true, 2, 3, |
110 | MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), |
111 | FMT(BGR565, 0, 5, 6, 5, 2, 0, 1, 0, false, true, 2, 3, |
112 | MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), |
113 | |
114 | /* --- RGB formats above / YUV formats below this line --- */ |
115 | |
116 | /* 2 plane YUV */ |
117 | FMT(NV12, 0, 8, 8, 8, 1, 2, 0, 0, false, true, 2, 2, |
118 | MDP_PLANE_PSEUDO_PLANAR, CHROMA_420, true), |
119 | FMT(NV21, 0, 8, 8, 8, 2, 1, 0, 0, false, true, 2, 2, |
120 | MDP_PLANE_PSEUDO_PLANAR, CHROMA_420, true), |
121 | FMT(NV16, 0, 8, 8, 8, 1, 2, 0, 0, false, true, 2, 2, |
122 | MDP_PLANE_PSEUDO_PLANAR, CHROMA_H2V1, true), |
123 | FMT(NV61, 0, 8, 8, 8, 2, 1, 0, 0, false, true, 2, 2, |
124 | MDP_PLANE_PSEUDO_PLANAR, CHROMA_H2V1, true), |
125 | /* 1 plane YUV */ |
126 | FMT(VYUY, 0, 8, 8, 8, 2, 0, 1, 0, false, true, 2, 4, |
127 | MDP_PLANE_INTERLEAVED, CHROMA_H2V1, true), |
128 | FMT(UYVY, 0, 8, 8, 8, 1, 0, 2, 0, false, true, 2, 4, |
129 | MDP_PLANE_INTERLEAVED, CHROMA_H2V1, true), |
130 | FMT(YUYV, 0, 8, 8, 8, 0, 1, 0, 2, false, true, 2, 4, |
131 | MDP_PLANE_INTERLEAVED, CHROMA_H2V1, true), |
132 | FMT(YVYU, 0, 8, 8, 8, 0, 2, 0, 1, false, true, 2, 4, |
133 | MDP_PLANE_INTERLEAVED, CHROMA_H2V1, true), |
134 | /* 3 plane YUV */ |
135 | FMT(YUV420, 0, 8, 8, 8, 2, 1, 0, 0, false, true, 1, 1, |
136 | MDP_PLANE_PLANAR, CHROMA_420, true), |
137 | FMT(YVU420, 0, 8, 8, 8, 1, 2, 0, 0, false, true, 1, 1, |
138 | MDP_PLANE_PLANAR, CHROMA_420, true), |
139 | }; |
140 | |
141 | /* |
142 | * Note: |
143 | * @rgb_only must be set to true, when requesting |
144 | * supported formats for RGB pipes. |
145 | */ |
146 | uint32_t mdp_get_formats(uint32_t *pixel_formats, uint32_t max_formats, |
147 | bool rgb_only) |
148 | { |
149 | uint32_t i; |
150 | for (i = 0; i < ARRAY_SIZE(formats); i++) { |
151 | const struct mdp_format *f = &formats[i]; |
152 | |
153 | if (i == max_formats) |
154 | break; |
155 | |
156 | if (rgb_only && MDP_FORMAT_IS_YUV(f)) |
157 | break; |
158 | |
159 | pixel_formats[i] = f->base.pixel_format; |
160 | } |
161 | |
162 | return i; |
163 | } |
164 | |
165 | const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format, |
166 | uint64_t modifier) |
167 | { |
168 | int i; |
169 | for (i = 0; i < ARRAY_SIZE(formats); i++) { |
170 | const struct mdp_format *f = &formats[i]; |
171 | if (f->base.pixel_format == format) |
172 | return &f->base; |
173 | } |
174 | return NULL; |
175 | } |
176 | |
177 | struct csc_cfg *mdp_get_default_csc_cfg(enum csc_type type) |
178 | { |
179 | if (WARN_ON(type >= CSC_MAX)) |
180 | return NULL; |
181 | |
182 | return &csc_convert[type]; |
183 | } |
184 | |