1 # --- T2-COPYRIGHT-NOTE-BEGIN ---
2 # This copyright note is auto-generated by scripts/Create-CopyPatch.
4 # T2 SDE: architecture/powerpc64/package/.../0020-ps3fb-use-fifo.patch
5 # Copyright (C) 2020 The T2 SDE Project
7 # More information can be found in the files COPYING and README.
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
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
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
33 static inline int lv1_gpu_display_sync(u64 context_handle, u64 head,
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
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 */
58 +struct gpu_graph_exception_info {
70 + u32 fifo_cache[512];
71 + u32 graph_fifo[512];
87 + struct gpu_graph_exception_info graph_exception_info;
90 struct gpu_driver_info {
95 +struct gpu_fifo_ctrl {
103 + volatile struct gpu_fifo_ctrl *ctrl;
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[] = {
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 */
224 + dev_err(dev, "%s: lv1_gpu_context_attribute failed (%d)\n",
231 + fifo_ctrl->put += (fifo->curr - fifo_prev) * sizeof(u32);
233 + /* wait until FIFO is done */
235 + while (timeout--) {
236 + if (fifo_ctrl->put == fifo_ctrl->get)
240 + if (fifo_ctrl->put != fifo_ctrl->get)
241 + retval = -ETIMEDOUT;
245 + pr_debug("%s: leave (%d)\n", __func__, 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,
256 +#define BLEN 0x400UL
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;
276 + fifo_ctrl->put = fifo->ioif;
278 + /* wait until FIFO is done */
280 + while (timeout--) {
281 + if (fifo_ctrl->put == fifo_ctrl->get)
285 + if (fifo_ctrl->put != fifo_ctrl->get) {
286 + retval = -ETIMEDOUT;
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 */
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.
315 + dy = (h <= BLEN) ? h : BLEN;
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;
355 + /* wait for idle */
356 + *fifo->curr++ = 0x00040110;
357 + *fifo->curr++ = 0x00000000;
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) {
366 + while (timeout--) {
367 + if (fifo_ctrl->put == fifo_ctrl->get)
371 + if (fifo_ctrl->put != fifo_ctrl->get)
372 + retval = -ETIMEDOUT;
377 + pr_debug("%s: leave (%d)\n", __func__, retval);
384 static int ps3fb_cmp_mode(const struct fb_videomode *vmode,
385 const struct fb_var_screeninfo *var)
387 @@ -444,24 +733,20 @@
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,
405 + status = ps3fb_fb_blit(&ps3fb.fifo,
407 + GPU_IOIF + src_offset,
409 + dst_line_length, src_line_length,
410 + L1GPU_FB_BLIT_WAIT_FOR_COMPLETION);
411 mutex_unlock(&ps3_gpu_mutex);
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__,
418 status = lv1_gpu_display_flip(ps3fb.context_handle, 0, frame_offset);
419 @@ -912,6 +1197,34 @@
423 +static void ps3fb_print_graph_exception_info(struct device *dev,
424 + struct gpu_graph_exception_info *info)
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" : " "),
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 @@
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)) {
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);
476 dev_err(&dev->core, "%s: lv1_gpu_memory_allocate failed: %d\n",
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);
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);
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",
521 - goto err_context_unmap;
523 + goto err_iounmap_fifo_ctrl;
526 info = framebuffer_alloc(sizeof(struct ps3fb_par), &dev->core);
529 - goto err_context_fb_close;
530 + goto err_iounmap_fifo_ctrl;
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);
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);