* updated kollision (21.12.1 -> 21.12.2), untested
[t2-trunk.git] / architecture / powerpc64 / package / linux / 0020-ps3fb-use-fifo.patch
blob559530091dcdea5edd4f117c1f4a3a4f546f85ac
1 # --- T2-COPYRIGHT-NOTE-BEGIN ---
2 # This copyright note is auto-generated by scripts/Create-CopyPatch.
3 #
4 # T2 SDE: architecture/powerpc64/package/.../0020-ps3fb-use-fifo.patch
5 # Copyright (C) 2020 The T2 SDE Project
6 #
7 # More information can be found in the files COPYING and README.
8 #
9 # This patch file is dual-licensed. It is available under the license the
10 # patched project is licensed under, as long as it is an OpenSource license
11 # as defined at http://www.opensource.org/ (e.g. BSD, X11) or under the terms
12 # of the GNU General Public License as published by the Free Software
13 # Foundation; either version 2 of the License, or (at your option) any later
14 # version.
15 # --- T2-COPYRIGHT-NOTE-END ---
17 --- a/arch/powerpc/include/asm/ps3gpu.h 2012-01-03 19:41:27.000000000 +0100
18 +++ b/arch/powerpc/include/asm/ps3gpu.h 2012-01-05 23:17:51.200679863 +0100
19 @@ -25,6 +25,10 @@
20 #include <asm/lv1call.h>
23 +#define L1GPU_CONTEXT_ATTRIBUTE_FIFO_SETUP 0x1
24 +#define L1GPU_CONTEXT_ATTRIBUTE_FIFO_PAUSE 0x2
25 +#define L1GPU_CONTEXT_ATTRIBUTE_FIFO_RESUME 0x3
27 #define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC 0x101
28 #define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP 0x102
30 @@ -44,11 +48,11 @@
33 static inline int lv1_gpu_display_sync(u64 context_handle, u64 head,
34 - u64 ddr_offset)
35 + u64 sync_mode)
37 return lv1_gpu_context_attribute(context_handle,
38 L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
39 - head, ddr_offset, 0, 0);
40 + head, sync_mode, 0, 0);
43 static inline int lv1_gpu_display_flip(u64 context_handle, u64 head,
44 --- a/drivers/video/fbdev/ps3fb.c 2012-01-03 19:41:27.000000000 +0100
45 +++ b/drivers/video/fbdev/ps3fb.c 2012-01-05 23:17:32.550387632 +0100
46 @@ -50,6 +50,7 @@
48 #define GPU_INTR_STATUS_VSYNC_0 0 /* vsync on head A */
49 #define GPU_INTR_STATUS_VSYNC_1 1 /* vsync on head B */
50 +#define GPU_INTR_STATUS_GRAPH_EXCEPTION 2 /* graphics exception */
51 #define GPU_INTR_STATUS_FLIP_0 3 /* flip head A */
52 #define GPU_INTR_STATUS_FLIP_1 4 /* flip head B */
53 #define GPU_INTR_STATUS_QUEUE_0 5 /* queue head A */
54 @@ -75,6 +76,22 @@
55 u32 reserved2;
58 +struct gpu_graph_exception_info {
59 + u32 channel_id;
60 + u32 cause;
61 + u32 res1[8];
62 + u32 dma_put;
63 + u32 dma_get;
64 + u32 call;
65 + u32 jump;
66 + u32 res2;
67 + u32 fifo_put;
68 + u32 fifo_get;
69 + u32 fifo_ref;
70 + u32 fifo_cache[512];
71 + u32 graph_fifo[512];
72 +};
74 struct gpu_irq {
75 u32 irq_outlet;
76 u32 status;
77 @@ -82,11 +99,8 @@
78 u32 video_cause;
79 u32 graph_cause;
80 u32 user_cause;
82 - u32 res1;
83 - u64 res2;
85 - u32 reserved[4];
86 + u32 res[8];
87 + struct gpu_graph_exception_info graph_exception_info;
90 struct gpu_driver_info {
91 @@ -103,11 +117,27 @@
92 struct gpu_irq irq;
95 +struct gpu_fifo_ctrl {
96 + u8 res[64];
97 + u32 put;
98 + u32 get;
99 + u32 ref;
102 +struct gpu_fifo {
103 + volatile struct gpu_fifo_ctrl *ctrl;
104 + u32 *start;
105 + u32 *curr;
106 + unsigned int len;
107 + u32 ioif;
110 struct ps3fb_priv {
111 unsigned int irq_no;
113 u64 context_handle, memory_handle;
114 struct gpu_driver_info *dinfo;
115 + struct gpu_fifo fifo;
117 u64 vblank_count; /* frame count */
118 wait_queue_head_t wait_vsync;
119 @@ -260,8 +290,267 @@
120 static int ps3fb_mode;
121 module_param(ps3fb_mode, int, 0);
123 +static unsigned long ps3fb_gpu_ctx_flags = 0x820;
124 +module_param(ps3fb_gpu_ctx_flags, ulong, 0);
126 +static unsigned long ps3fb_gpu_mem_size[4];
127 +static int ps3fb_gpu_mem_size_count;
128 +module_param_array(ps3fb_gpu_mem_size, ulong, &ps3fb_gpu_mem_size_count, 0);
130 static char *mode_option;
132 +static int ps3fb_fb_setup(struct device *dev,
133 + u64 context_handle,
134 + struct gpu_fifo *fifo)
136 + /* FIFO program for L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP from LV1 */
137 + const static u32 fifo_setup_program[] = {
138 + 0x00042000,
139 + 0x31337303,
141 + 0x00042180,
142 + 0x66604200,
144 + 0x00082184,
145 + 0xFEED0001,
146 + 0xFEED0000,
148 + 0x00044000,
149 + 0x3137C0DE,
151 + 0x00044180,
152 + 0x66604200,
154 + 0x00084184,
155 + 0xFEED0000,
156 + 0xFEED0001,
158 + 0x00046000,
159 + 0x313371C3,
161 + 0x00046180,
162 + 0x66604200,
164 + 0x00046184,
165 + 0xFEED0000,
167 + 0x00046188,
168 + 0xFEED0000,
170 + 0x0004A000,
171 + 0x31337808,
173 + 0x0020A180,
174 + 0x66604200,
175 + 0x00000000,
176 + 0x00000000,
177 + 0x00000000,
178 + 0x00000000,
179 + 0x00000000,
180 + 0x00000000,
181 + 0x313371C3,
183 + 0x0008A2FC,
184 + 0x00000003,
185 + 0x00000004,
187 + 0x00048000,
188 + 0x31337A73,
190 + 0x00048180,
191 + 0x66604200,
193 + 0x00048184,
194 + 0xFEED0000,
196 + 0x0004C000,
197 + 0x3137AF00,
199 + 0x0004C180,
200 + 0x66604200,
202 + 0x00000000,
203 + };
204 + int retval = 0;
205 + int status;
206 + volatile struct gpu_fifo_ctrl *fifo_ctrl = fifo->ctrl;
207 + u32 *fifo_prev = fifo->curr;
208 + unsigned int timeout;
210 + pr_debug("%s: enter\n", __func__);
212 + /* copy setup program to FIFO */
213 + memcpy(fifo->curr, fifo_setup_program, sizeof(fifo_setup_program));
214 + fifo->curr += sizeof(fifo_setup_program) / sizeof(u32);
216 + /* set PUT and GET registers */
217 + status = lv1_gpu_context_attribute(context_handle,
218 + L1GPU_CONTEXT_ATTRIBUTE_FIFO_SETUP,
219 + fifo->ioif, /* PUT */
220 + fifo->ioif, /* GET */
221 + 0, /* REF */
222 + 0);
223 + if (status) {
224 + dev_err(dev, "%s: lv1_gpu_context_attribute failed (%d)\n",
225 + __func__, status);
226 + retval = -ENXIO;
227 + goto done;
230 + /* kick FIFO */
231 + fifo_ctrl->put += (fifo->curr - fifo_prev) * sizeof(u32);
233 + /* wait until FIFO is done */
234 + timeout = 100000;
235 + while (timeout--) {
236 + if (fifo_ctrl->put == fifo_ctrl->get)
237 + break;
240 + if (fifo_ctrl->put != fifo_ctrl->get)
241 + retval = -ETIMEDOUT;
243 +done:
245 + pr_debug("%s: leave (%d)\n", __func__, retval);
247 + return (retval);
250 +static int ps3fb_fb_blit(struct gpu_fifo *fifo,
251 + u64 dst_offset, u64 src_offset,
252 + u32 width, u32 height,
253 + u32 dst_pitch, u32 src_pitch,
254 + u64 flags)
256 +#define BLEN 0x400UL
258 + int retval = 0;
259 + volatile struct gpu_fifo_ctrl *fifo_ctrl = fifo->ctrl;
260 + u32 *fifo_prev = fifo->curr;
261 + unsigned int timeout;
262 + u32 h, w, x, y, dx, dy;
264 + //pr_debug("%s: enter\n", __func__);
266 + /* check if there is enough free space in FIFO */
267 + if ((fifo->len - ((fifo->curr - fifo->start) * sizeof(u32))) < 0x1000) {
268 + /* no, jump back to FIFO start */
270 + pr_debug("%s: not enough free space left in FIFO put (0x%08x) get (0x%08x)\n",
271 + __func__, fifo_ctrl->put, fifo_ctrl->get);
273 + *fifo->curr++ = 0x20000000 /* JMP */ | fifo->ioif;
275 + /* kick FIFO */
276 + fifo_ctrl->put = fifo->ioif;
278 + /* wait until FIFO is done */
279 + timeout = 100000;
280 + while (timeout--) {
281 + if (fifo_ctrl->put == fifo_ctrl->get)
282 + break;
285 + if (fifo_ctrl->put != fifo_ctrl->get) {
286 + retval = -ETIMEDOUT;
287 + goto done;
290 + fifo->curr = fifo->start;
291 + fifo_prev = fifo->curr;
294 + /* FIFO program for L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT from LV1 (transfer image) */
296 + /* set source location */
297 + *fifo->curr++ = 0x0004C184;
298 + *fifo->curr++ = 0xFEED0001; /* GART memory */
300 + *fifo->curr++ = 0x0004C198;
301 + *fifo->curr++ = 0x313371C3;
303 + *fifo->curr++ = 0x00046300;
304 + *fifo->curr++ = 0x0000000A; /* 4 bytes per pixel */
306 + /*
307 + * Transfer data in a block-wise fashion with block size 1024x1024x4 bytes
308 + * by using RSX DMA controller. Go from top to bottom and from left to right.
309 + */
311 + h = height;
312 + y = 0;
314 + while (h) {
315 + dy = (h <= BLEN) ? h : BLEN;
317 + w = width;
318 + x = 0;
320 + while (w) {
321 + dx = (w <= BLEN) ? w : BLEN;
323 + *fifo->curr++ = 0x0004630C;
324 + *fifo->curr++ = dst_offset + (y & ~(BLEN - 1)) * dst_pitch + (x & ~(BLEN - 1)) * BPP; /* destination */
326 + *fifo->curr++ = 0x00046304;
327 + *fifo->curr++ = (dst_pitch << 16) | dst_pitch;
329 + *fifo->curr++ = 0x0024C2FC;
330 + *fifo->curr++ = 0x00000001;
331 + *fifo->curr++ = 0x00000003; /* 4 bytes per pixel */
332 + *fifo->curr++ = 0x00000003;
333 + *fifo->curr++ = ((x & (BLEN - 1)) << 16) | (y & (BLEN - 1));
334 + *fifo->curr++ = (dy << 16) | dx;
335 + *fifo->curr++ = ((x & (BLEN - 1)) << 16) | (y & (BLEN - 1));
336 + *fifo->curr++ = (dy << 16) | dx;
337 + *fifo->curr++ = 0x00100000;
338 + *fifo->curr++ = 0x00100000;
340 + *fifo->curr++ = 0x0010C400;
341 + *fifo->curr++ = (dy << 16) | ((dx < 0x10) ? 0x10 : (dx + 1) & ~0x1);
342 + *fifo->curr++ = 0x00020000 | src_pitch;
343 + *fifo->curr++ = src_offset + y * src_pitch + x * BPP; /* source */
344 + *fifo->curr++ = 0x00000000;
346 + w -= dx;
347 + x += dx;
350 + h -= dy;
351 + y += dy;
354 +#if 0
355 + /* wait for idle */
356 + *fifo->curr++ = 0x00040110;
357 + *fifo->curr++ = 0x00000000;
358 +#endif
360 + /* kick FIFO */
361 + fifo_ctrl->put += (fifo->curr - fifo_prev) * sizeof(u32);
363 + /* wait until FIFO is done */
364 + if (flags & L1GPU_FB_BLIT_WAIT_FOR_COMPLETION) {
365 + timeout = 100000;
366 + while (timeout--) {
367 + if (fifo_ctrl->put == fifo_ctrl->get)
368 + break;
371 + if (fifo_ctrl->put != fifo_ctrl->get)
372 + retval = -ETIMEDOUT;
375 +done:
377 + pr_debug("%s: leave (%d)\n", __func__, retval);
379 + return (retval);
381 +#undef BLEN
384 static int ps3fb_cmp_mode(const struct fb_videomode *vmode,
385 const struct fb_var_screeninfo *var)
387 @@ -444,24 +733,20 @@
388 u32 src_line_length)
390 int status;
391 - u64 line_length;
393 - line_length = dst_line_length;
394 - if (src_line_length != dst_line_length)
395 - line_length |= (u64)src_line_length << 32;
397 src_offset += GPU_FB_START;
399 mutex_lock(&ps3_gpu_mutex);
400 - status = lv1_gpu_fb_blit(ps3fb.context_handle, dst_offset,
401 - GPU_IOIF + src_offset,
402 - L1GPU_FB_BLIT_WAIT_FOR_COMPLETION |
403 - (width << 16) | height,
404 - line_length);
405 + status = ps3fb_fb_blit(&ps3fb.fifo,
406 + dst_offset,
407 + GPU_IOIF + src_offset,
408 + width, height,
409 + dst_line_length, src_line_length,
410 + L1GPU_FB_BLIT_WAIT_FOR_COMPLETION);
411 mutex_unlock(&ps3_gpu_mutex);
413 if (status)
414 - dev_err(dev, "%s: lv1_gpu_fb_blit failed: %d\n", __func__,
415 + dev_err(dev, "%s: ps3fb_fb_blit failed: %d\n", __func__,
416 status);
417 #ifdef HEAD_A
418 status = lv1_gpu_display_flip(ps3fb.context_handle, 0, frame_offset);
419 @@ -912,6 +1197,34 @@
420 return 0;
423 +static void ps3fb_print_graph_exception_info(struct device *dev,
424 + struct gpu_graph_exception_info *info)
426 + int i;
428 + dev_err(dev, "channel id 0x%08x cause 0x%08x\n", info->channel_id, info->cause);
430 + /* print FIFO info */
432 + dev_err(dev, "fifo:\n");
433 + dev_err(dev, "\tdma get 0x%08x dma put 0x%08x\n",
434 + info->dma_get, info->dma_put);
435 + dev_err(dev, "\tcall 0x%08x jump 0x%08x\n", info->call, info->jump);
436 + dev_err(dev, "\tget 0x%08x put 0x%08x ref 0x%08x\n",
437 + info->fifo_get, info->fifo_put, info->fifo_ref);
439 + for (i = 0; i < 512; i += 4) {
440 + dev_err(dev, "\t%s %s [%03x] %08x:%08x %08x:%08x %08x:%08x %08x:%08x\n",
441 + (((info->fifo_put & ~0x3) == i) ? "P" : " "),
442 + (((info->fifo_get & ~0x3) == i) ? "G" : " "),
443 + i,
444 + info->fifo_cache[i * 4 + 0], info->graph_fifo[i * 4 + 0],
445 + info->fifo_cache[i * 4 + 1], info->graph_fifo[i * 4 + 1],
446 + info->fifo_cache[i * 4 + 2], info->graph_fifo[i * 4 + 2],
447 + info->fifo_cache[i * 4 + 3], info->graph_fifo[i * 4 + 3]);
451 static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr)
453 struct device *dev = ptr;
454 @@ -926,6 +1239,11 @@
455 return IRQ_NONE;
458 + if (v1 & (1 << GPU_INTR_STATUS_GRAPH_EXCEPTION)) {
459 + dev_err(dev, "%s: graphics exception\n", __func__);
460 + ps3fb_print_graph_exception_info(dev, &ps3fb.dinfo->irq.graph_exception_info);
463 if (v1 & (1 << GPU_INTR_STATUS_VSYNC_1)) {
464 /* VSYNC */
465 ps3fb.vblank_count = head->vblank_count;
466 @@ -1030,8 +1348,9 @@
469 /* get gpu context handle */
470 - status = lv1_gpu_memory_allocate(ps3fb_videomemory.size, 0, 0, 0, 0,
471 - &ps3fb.memory_handle, &ddr_lpar);
472 + status = lv1_gpu_memory_allocate(ps3fb_videomemory.size, ps3fb_gpu_mem_size[0],
473 + ps3fb_gpu_mem_size[1], ps3fb_gpu_mem_size[2], ps3fb_gpu_mem_size[3],
474 + &ps3fb.memory_handle, &ddr_lpar);
475 if (status) {
476 dev_err(&dev->core, "%s: lv1_gpu_memory_allocate failed: %d\n",
477 __func__, status);
478 @@ -1039,7 +1358,7 @@
480 dev_dbg(&dev->core, "ddr:lpar:0x%llx\n", ddr_lpar);
482 - status = lv1_gpu_context_allocate(ps3fb.memory_handle, 0,
483 + status = lv1_gpu_context_allocate(ps3fb.memory_handle, ps3fb_gpu_ctx_flags,
484 &ps3fb.context_handle,
485 &lpar_dma_control, &lpar_driver_info,
486 &lpar_reports, &lpar_reports_size);
487 @@ -1089,7 +1408,8 @@
488 goto err_destroy_plug;
491 - dinfo->irq.mask = (1 << GPU_INTR_STATUS_VSYNC_1) |
492 + dinfo->irq.mask = (1 << GPU_INTR_STATUS_GRAPH_EXCEPTION) |
493 + (1 << GPU_INTR_STATUS_VSYNC_1) |
494 (1 << GPU_INTR_STATUS_FLIP_1);
496 /* Clear memory to prevent kernel info leakage into userspace */
497 @@ -1434,19 +1434,30 @@
498 ps3fb_videomemory.address, GPU_IOIF, xdr_lpar,
499 ps3fb_videomemory.size);
501 - status = lv1_gpu_fb_setup(ps3fb.context_handle, xdr_lpar,
502 - GPU_CMD_BUF_SIZE, GPU_IOIF);
503 + /* FIFO control */
504 + ps3fb.fifo.ctrl = (void __force *)ioremap(lpar_dma_control, PAGE_SIZE);
505 + if (!ps3fb.fifo.ctrl) {
506 + dev_err(&dev->core, "%s: ioremap failed\n", __func__);
507 + goto err_context_unmap;
510 + ps3fb.fifo.start = ps3fb_videomemory.address;
511 + ps3fb.fifo.curr = ps3fb.fifo.start;
512 + ps3fb.fifo.len = GPU_FB_START;
513 + ps3fb.fifo.ioif = GPU_IOIF;
515 + status = ps3fb_fb_setup(&dev->core, ps3fb.context_handle, &ps3fb.fifo);
516 if (status) {
517 - dev_err(&dev->core, "%s: lv1_gpu_fb_setup failed: %d\n",
518 + dev_err(&dev->core, "%s: ps3fb_fb_setup failed: %d\n",
519 __func__, status);
520 - retval = -ENXIO;
521 - goto err_context_unmap;
522 + retval = status;
523 + goto err_iounmap_fifo_ctrl;
526 info = framebuffer_alloc(sizeof(struct ps3fb_par), &dev->core);
527 if (!info) {
528 retval = -ENOMEM;
529 - goto err_context_fb_close;
530 + goto err_iounmap_fifo_ctrl;
533 par = info->par;
534 @@ -1188,8 +1519,8 @@
535 fb_dealloc_cmap(&info->cmap);
536 err_framebuffer_release:
537 framebuffer_release(info);
538 -err_context_fb_close:
539 - lv1_gpu_fb_close(ps3fb.context_handle);
540 +err_iounmap_fifo_ctrl:
541 + iounmap((u8 __force __iomem *)ps3fb.fifo.ctrl);
542 err_context_unmap:
543 lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF, xdr_lpar,
544 ps3fb_videomemory.size, CBE_IOPTE_M);
545 @@ -1235,7 +1566,7 @@
546 ps3_system_bus_set_drvdata(dev, NULL);
548 iounmap((u8 __force __iomem *)ps3fb.dinfo);
549 - lv1_gpu_fb_close(ps3fb.context_handle);
550 + iounmap((u8 __force __iomem *)ps3fb.fifo.ctrl);
551 lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF, xdr_lpar,
552 ps3fb_videomemory.size, CBE_IOPTE_M);
553 lv1_gpu_context_free(ps3fb.context_handle);