]> Git Repo - linux.git/blob - drivers/gpu/drm/drm_format_helper.c
drm/amdgpu: amdgpu_device_recover_vram got NULL of shadow->parent
[linux.git] / drivers / gpu / drm / drm_format_helper.c
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Copyright (C) 2016 Noralf Trønnes
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  */
10
11 #include <linux/module.h>
12 #include <linux/slab.h>
13
14 #include <drm/drm_format_helper.h>
15 #include <drm/drm_framebuffer.h>
16 #include <drm/drm_fourcc.h>
17 #include <drm/drm_rect.h>
18
19 static void drm_fb_memcpy_lines(void *dst, unsigned int dst_pitch,
20                                 void *src, unsigned int src_pitch,
21                                 unsigned int linelength, unsigned int lines)
22 {
23         int line;
24
25         for (line = 0; line < lines; line++) {
26                 memcpy(dst, src, linelength);
27                 src += src_pitch;
28                 dst += dst_pitch;
29         }
30 }
31
32 /**
33  * drm_fb_memcpy - Copy clip buffer
34  * @dst: Destination buffer
35  * @vaddr: Source buffer
36  * @fb: DRM framebuffer
37  * @clip: Clip rectangle area to copy
38  *
39  * This function does not apply clipping on dst, i.e. the destination
40  * is a small buffer containing the clip rect only.
41  */
42 void drm_fb_memcpy(void *dst, void *vaddr, struct drm_framebuffer *fb,
43                    struct drm_rect *clip)
44 {
45         unsigned int cpp = drm_format_plane_cpp(fb->format->format, 0);
46         unsigned int offset = (clip->y1 * fb->pitches[0]) + (clip->x1 * cpp);
47         size_t len = (clip->x2 - clip->x1) * cpp;
48
49         drm_fb_memcpy_lines(dst, len,
50                             vaddr + offset, fb->pitches[0],
51                             len, clip->y2 - clip->y1);
52 }
53 EXPORT_SYMBOL(drm_fb_memcpy);
54
55 /**
56  * drm_fb_memcpy_dstclip - Copy clip buffer
57  * @dst: Destination buffer
58  * @vaddr: Source buffer
59  * @fb: DRM framebuffer
60  * @clip: Clip rectangle area to copy
61  *
62  * This function applies clipping on dst, i.e. the destination is a
63  * full framebuffer but only the clip rect content is copied over.
64  */
65 void drm_fb_memcpy_dstclip(void *dst, void *vaddr, struct drm_framebuffer *fb,
66                            struct drm_rect *clip)
67 {
68         unsigned int cpp = drm_format_plane_cpp(fb->format->format, 0);
69         unsigned int offset = (clip->y1 * fb->pitches[0]) + (clip->x1 * cpp);
70         size_t len = (clip->x2 - clip->x1) * cpp;
71
72         drm_fb_memcpy_lines(dst + offset, fb->pitches[0],
73                             vaddr + offset, fb->pitches[0],
74                             len, clip->y2 - clip->y1);
75 }
76 EXPORT_SYMBOL(drm_fb_memcpy_dstclip);
77
78 /**
79  * drm_fb_swab16 - Swap bytes into clip buffer
80  * @dst: RGB565 destination buffer
81  * @vaddr: RGB565 source buffer
82  * @fb: DRM framebuffer
83  * @clip: Clip rectangle area to copy
84  */
85 void drm_fb_swab16(u16 *dst, void *vaddr, struct drm_framebuffer *fb,
86                    struct drm_rect *clip)
87 {
88         size_t len = (clip->x2 - clip->x1) * sizeof(u16);
89         unsigned int x, y;
90         u16 *src, *buf;
91
92         /*
93          * The cma memory is write-combined so reads are uncached.
94          * Speed up by fetching one line at a time.
95          */
96         buf = kmalloc(len, GFP_KERNEL);
97         if (!buf)
98                 return;
99
100         for (y = clip->y1; y < clip->y2; y++) {
101                 src = vaddr + (y * fb->pitches[0]);
102                 src += clip->x1;
103                 memcpy(buf, src, len);
104                 src = buf;
105                 for (x = clip->x1; x < clip->x2; x++)
106                         *dst++ = swab16(*src++);
107         }
108
109         kfree(buf);
110 }
111 EXPORT_SYMBOL(drm_fb_swab16);
112
113 static void drm_fb_xrgb8888_to_rgb565_lines(void *dst, unsigned int dst_pitch,
114                                             void *src, unsigned int src_pitch,
115                                             unsigned int src_linelength,
116                                             unsigned int lines,
117                                             bool swap)
118 {
119         unsigned int linepixels = src_linelength / sizeof(u32);
120         unsigned int x, y;
121         u32 *sbuf;
122         u16 *dbuf, val16;
123
124         /*
125          * The cma memory is write-combined so reads are uncached.
126          * Speed up by fetching one line at a time.
127          */
128         sbuf = kmalloc(src_linelength, GFP_KERNEL);
129         if (!sbuf)
130                 return;
131
132         for (y = 0; y < lines; y++) {
133                 memcpy(sbuf, src, src_linelength);
134                 dbuf = dst;
135                 for (x = 0; x < linepixels; x++) {
136                         val16 = ((sbuf[x] & 0x00F80000) >> 8) |
137                                 ((sbuf[x] & 0x0000FC00) >> 5) |
138                                 ((sbuf[x] & 0x000000F8) >> 3);
139                         if (swap)
140                                 *dbuf++ = swab16(val16);
141                         else
142                                 *dbuf++ = val16;
143                 }
144                 src += src_pitch;
145                 dst += dst_pitch;
146         }
147
148         kfree(sbuf);
149 }
150
151 /**
152  * drm_fb_xrgb8888_to_rgb565 - Convert XRGB8888 to RGB565 clip buffer
153  * @dst: RGB565 destination buffer
154  * @vaddr: XRGB8888 source buffer
155  * @fb: DRM framebuffer
156  * @clip: Clip rectangle area to copy
157  * @swap: Swap bytes
158  *
159  * Drivers can use this function for RGB565 devices that don't natively
160  * support XRGB8888.
161  *
162  * This function does not apply clipping on dst, i.e. the destination
163  * is a small buffer containing the clip rect only.
164  */
165 void drm_fb_xrgb8888_to_rgb565(void *dst, void *vaddr,
166                                struct drm_framebuffer *fb,
167                                struct drm_rect *clip, bool swap)
168 {
169         unsigned int src_offset = (clip->y1 * fb->pitches[0])
170                 + (clip->x1 * sizeof(u32));
171         size_t src_len = (clip->x2 - clip->x1) * sizeof(u32);
172         size_t dst_len = (clip->x2 - clip->x1) * sizeof(u16);
173
174         drm_fb_xrgb8888_to_rgb565_lines(dst, dst_len,
175                                         vaddr + src_offset, fb->pitches[0],
176                                         src_len, clip->y2 - clip->y1,
177                                         swap);
178 }
179 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565);
180
181 /**
182  * drm_fb_xrgb8888_to_rgb565_dstclip - Convert XRGB8888 to RGB565 clip buffer
183  * @dst: RGB565 destination buffer
184  * @dst_pitch: destination buffer pitch
185  * @vaddr: XRGB8888 source buffer
186  * @fb: DRM framebuffer
187  * @clip: Clip rectangle area to copy
188  * @swap: Swap bytes
189  *
190  * Drivers can use this function for RGB565 devices that don't natively
191  * support XRGB8888.
192  *
193  * This function applies clipping on dst, i.e. the destination is a
194  * full framebuffer but only the clip rect content is copied over.
195  */
196 void drm_fb_xrgb8888_to_rgb565_dstclip(void *dst, unsigned int dst_pitch,
197                                        void *vaddr, struct drm_framebuffer *fb,
198                                        struct drm_rect *clip, bool swap)
199 {
200         unsigned int src_offset = (clip->y1 * fb->pitches[0])
201                 + (clip->x1 * sizeof(u32));
202         unsigned int dst_offset = (clip->y1 * dst_pitch)
203                 + (clip->x1 * sizeof(u16));
204         size_t src_len = (clip->x2 - clip->x1) * sizeof(u32);
205
206         drm_fb_xrgb8888_to_rgb565_lines(dst + dst_offset, dst_pitch,
207                                         vaddr + src_offset, fb->pitches[0],
208                                         src_len, clip->y2 - clip->y1,
209                                         swap);
210 }
211 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565_dstclip);
212
213 static void drm_fb_xrgb8888_to_rgb888_lines(void *dst, unsigned int dst_pitch,
214                                             void *src, unsigned int src_pitch,
215                                             unsigned int src_linelength,
216                                             unsigned int lines)
217 {
218         unsigned int linepixels = src_linelength / 3;
219         unsigned int x, y;
220         u32 *sbuf;
221         u8 *dbuf;
222
223         sbuf = kmalloc(src_linelength, GFP_KERNEL);
224         if (!sbuf)
225                 return;
226
227         for (y = 0; y < lines; y++) {
228                 memcpy(sbuf, src, src_linelength);
229                 dbuf = dst;
230                 for (x = 0; x < linepixels; x++) {
231                         *dbuf++ = (sbuf[x] & 0x000000FF) >>  0;
232                         *dbuf++ = (sbuf[x] & 0x0000FF00) >>  8;
233                         *dbuf++ = (sbuf[x] & 0x00FF0000) >> 16;
234                 }
235                 src += src_pitch;
236                 dst += dst_pitch;
237         }
238
239         kfree(sbuf);
240 }
241
242 /**
243  * drm_fb_xrgb8888_to_rgb888_dstclip - Convert XRGB8888 to RGB888 clip buffer
244  * @dst: RGB565 destination buffer
245  * @dst_pitch: destination buffer pitch
246  * @vaddr: XRGB8888 source buffer
247  * @fb: DRM framebuffer
248  * @clip: Clip rectangle area to copy
249  * @dstclip: Clip destination too.
250  *
251  * Drivers can use this function for RGB888 devices that don't natively
252  * support XRGB8888.
253  *
254  * This function applies clipping on dst, i.e. the destination is a
255  * full framebuffer but only the clip rect content is copied over.
256  */
257 void drm_fb_xrgb8888_to_rgb888_dstclip(void *dst, unsigned int dst_pitch,
258                                        void *vaddr, struct drm_framebuffer *fb,
259                                        struct drm_rect *clip)
260 {
261         unsigned int src_offset = (clip->y1 * fb->pitches[0])
262                 + (clip->x1 * sizeof(u32));
263         unsigned int dst_offset = (clip->y1 * dst_pitch)
264                 + (clip->x1 * 3);
265         size_t src_len = (clip->x2 - clip->x1) * sizeof(u32);
266
267         drm_fb_xrgb8888_to_rgb888_lines(dst + dst_offset, dst_pitch,
268                                         vaddr + src_offset, fb->pitches[0],
269                                         src_len, clip->y2 - clip->y1);
270 }
271 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888_dstclip);
272
273 /**
274  * drm_fb_xrgb8888_to_gray8 - Convert XRGB8888 to grayscale
275  * @dst: 8-bit grayscale destination buffer
276  * @vaddr: XRGB8888 source buffer
277  * @fb: DRM framebuffer
278  * @clip: Clip rectangle area to copy
279  *
280  * Drm doesn't have native monochrome or grayscale support.
281  * Such drivers can announce the commonly supported XR24 format to userspace
282  * and use this function to convert to the native format.
283  *
284  * Monochrome drivers will use the most significant bit,
285  * where 1 means foreground color and 0 background color.
286  *
287  * ITU BT.601 is used for the RGB -> luma (brightness) conversion.
288  */
289 void drm_fb_xrgb8888_to_gray8(u8 *dst, void *vaddr, struct drm_framebuffer *fb,
290                                struct drm_rect *clip)
291 {
292         unsigned int len = (clip->x2 - clip->x1) * sizeof(u32);
293         unsigned int x, y;
294         void *buf;
295         u32 *src;
296
297         if (WARN_ON(fb->format->format != DRM_FORMAT_XRGB8888))
298                 return;
299         /*
300          * The cma memory is write-combined so reads are uncached.
301          * Speed up by fetching one line at a time.
302          */
303         buf = kmalloc(len, GFP_KERNEL);
304         if (!buf)
305                 return;
306
307         for (y = clip->y1; y < clip->y2; y++) {
308                 src = vaddr + (y * fb->pitches[0]);
309                 src += clip->x1;
310                 memcpy(buf, src, len);
311                 src = buf;
312                 for (x = clip->x1; x < clip->x2; x++) {
313                         u8 r = (*src & 0x00ff0000) >> 16;
314                         u8 g = (*src & 0x0000ff00) >> 8;
315                         u8 b =  *src & 0x000000ff;
316
317                         /* ITU BT.601: Y = 0.299 R + 0.587 G + 0.114 B */
318                         *dst++ = (3 * r + 6 * g + b) / 10;
319                         src++;
320                 }
321         }
322
323         kfree(buf);
324 }
325 EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8);
326
This page took 0.051091 seconds and 4 git commands to generate.