| 1 | /* |
| 2 | * SDL - Simple DirectMedia Layer |
| 3 | * CELL BE Support for PS3 Framebuffer |
| 4 | * Copyright (C) 2008, 2009 International Business Machines Corporation |
| 5 | * |
| 6 | * This library is free software; you can redistribute it and/or modify it |
| 7 | * under the terms of the GNU Lesser General Public License as published |
| 8 | * by the Free Software Foundation; either version 2.1 of the License, or |
| 9 | * (at your option) any later version. |
| 10 | * |
| 11 | * This library is distributed in the hope that it will be useful, but |
| 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 14 | * Lesser General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU Lesser General Public |
| 17 | * License along with this library; if not, write to the Free Software |
| 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 |
| 19 | * USA |
| 20 | * |
| 21 | * Martin Lowinski <lowinski [at] de [dot] ibm [ibm] com> |
| 22 | * Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com> |
| 23 | * SPE code based on research by: |
| 24 | * Rene Becker |
| 25 | * Thimo Emmerich |
| 26 | */ |
| 27 | |
| 28 | #include "spu_common.h" |
| 29 | |
| 30 | #include <spu_intrinsics.h> |
| 31 | #include <spu_mfcio.h> |
| 32 | #include <stdio.h> |
| 33 | #include <string.h> |
| 34 | |
| 35 | // Debugging |
| 36 | //#define DEBUG |
| 37 | |
| 38 | #ifdef DEBUG |
| 39 | #define deprintf(fmt, args... ) \ |
| 40 | fprintf( stdout, fmt, ##args ); \ |
| 41 | fflush( stdout ); |
| 42 | #else |
| 43 | #define deprintf( fmt, args... ) |
| 44 | #endif |
| 45 | |
| 46 | void cpy_to_fb(unsigned int); |
| 47 | |
| 48 | /* fb_writer_spu parms */ |
| 49 | static volatile struct fb_writer_parms_t parms __attribute__ ((aligned(128))); |
| 50 | |
| 51 | /* Code running on SPU */ |
| 52 | int main(unsigned long long spe_id __attribute__ ((unused)), unsigned long long argp __attribute__ ((unused))) |
| 53 | { |
| 54 | deprintf("[SPU] fb_writer_spu is up... (on SPE #%llu)\n", spe_id); |
| 55 | uint32_t ea_mfc, mbox; |
| 56 | // send ready message |
| 57 | spu_write_out_mbox(SPU_READY); |
| 58 | |
| 59 | while (1) { |
| 60 | /* Check mailbox */ |
| 61 | mbox = spu_read_in_mbox(); |
| 62 | deprintf("[SPU] Message is %u\n", mbox); |
| 63 | switch (mbox) { |
| 64 | case SPU_EXIT: |
| 65 | deprintf("[SPU] fb_writer goes down...\n"); |
| 66 | return 0; |
| 67 | case SPU_START: |
| 68 | break; |
| 69 | default: |
| 70 | deprintf("[SPU] Cannot handle message\n"); |
| 71 | continue; |
| 72 | } |
| 73 | |
| 74 | /* Tag Manager setup */ |
| 75 | unsigned int tags; |
| 76 | tags = mfc_multi_tag_reserve(5); |
| 77 | if (tags == MFC_TAG_INVALID) { |
| 78 | deprintf("[SPU] Failed to reserve mfc tags on fb_writer\n"); |
| 79 | return 0; |
| 80 | } |
| 81 | |
| 82 | /* Framebuffer parms */ |
| 83 | ea_mfc = spu_read_in_mbox(); |
| 84 | deprintf("[SPU] Message on fb_writer is %u\n", ea_mfc); |
| 85 | spu_mfcdma32(&parms, (unsigned int)ea_mfc, |
| 86 | sizeof(struct fb_writer_parms_t), tags, |
| 87 | MFC_GET_CMD); |
| 88 | deprintf("[SPU] argp = %u\n", (unsigned int)argp); |
| 89 | DMA_WAIT_TAG(tags); |
| 90 | |
| 91 | /* Copy parms->data to framebuffer */ |
| 92 | deprintf("[SPU] Copying to framebuffer started\n"); |
| 93 | cpy_to_fb(tags); |
| 94 | deprintf("[SPU] Copying to framebuffer done!\n"); |
| 95 | |
| 96 | mfc_multi_tag_release(tags, 5); |
| 97 | deprintf("[SPU] fb_writer_spu... done!\n"); |
| 98 | /* Send FIN msg */ |
| 99 | spu_write_out_mbox(SPU_FIN); |
| 100 | } |
| 101 | |
| 102 | return 0; |
| 103 | } |
| 104 | |
| 105 | void cpy_to_fb(unsigned int tag_id_base) |
| 106 | { |
| 107 | unsigned int i; |
| 108 | unsigned char current_buf; |
| 109 | uint8_t *in = parms.data; |
| 110 | |
| 111 | /* Align fb pointer which was centered before */ |
| 112 | uint8_t *fb = |
| 113 | (unsigned char *)((unsigned int)parms.center & 0xFFFFFFF0); |
| 114 | |
| 115 | uint32_t bounded_input_height = parms.bounded_input_height; |
| 116 | uint32_t bounded_input_width = parms.bounded_input_width; |
| 117 | uint32_t fb_pixel_size = parms.fb_pixel_size; |
| 118 | |
| 119 | uint32_t out_line_stride = parms.out_line_stride; |
| 120 | uint32_t in_line_stride = parms.in_line_stride; |
| 121 | uint32_t in_line_size = bounded_input_width * fb_pixel_size; |
| 122 | |
| 123 | current_buf = 0; |
| 124 | |
| 125 | /* Local store buffer */ |
| 126 | static volatile uint8_t buf[4][BUFFER_SIZE] |
| 127 | __attribute__ ((aligned(128))); |
| 128 | /* do 4-times multibuffering using DMA list, process in two steps */ |
| 129 | for (i = 0; i < bounded_input_height >> 2; i++) { |
| 130 | /* first buffer */ |
| 131 | DMA_WAIT_TAG(tag_id_base + 1); |
| 132 | // retrieve buffer |
| 133 | spu_mfcdma32(buf[0], (unsigned int)in, in_line_size, |
| 134 | tag_id_base + 1, MFC_GETB_CMD); |
| 135 | DMA_WAIT_TAG(tag_id_base + 1); |
| 136 | // store buffer |
| 137 | spu_mfcdma32(buf[0], (unsigned int)fb, in_line_size, |
| 138 | tag_id_base + 1, MFC_PUTB_CMD); |
| 139 | in += in_line_stride; |
| 140 | fb += out_line_stride; |
| 141 | deprintf("[SPU] 1st buffer copied in=0x%x, fb=0x%x\n", in, |
| 142 | fb); |
| 143 | |
| 144 | /* second buffer */ |
| 145 | DMA_WAIT_TAG(tag_id_base + 2); |
| 146 | // retrieve buffer |
| 147 | spu_mfcdma32(buf[1], (unsigned int)in, in_line_size, |
| 148 | tag_id_base + 2, MFC_GETB_CMD); |
| 149 | DMA_WAIT_TAG(tag_id_base + 2); |
| 150 | // store buffer |
| 151 | spu_mfcdma32(buf[1], (unsigned int)fb, in_line_size, |
| 152 | tag_id_base + 2, MFC_PUTB_CMD); |
| 153 | in += in_line_stride; |
| 154 | fb += out_line_stride; |
| 155 | deprintf("[SPU] 2nd buffer copied in=0x%x, fb=0x%x\n", in, |
| 156 | fb); |
| 157 | |
| 158 | /* third buffer */ |
| 159 | DMA_WAIT_TAG(tag_id_base + 3); |
| 160 | // retrieve buffer |
| 161 | spu_mfcdma32(buf[2], (unsigned int)in, in_line_size, |
| 162 | tag_id_base + 3, MFC_GETB_CMD); |
| 163 | DMA_WAIT_TAG(tag_id_base + 3); |
| 164 | // store buffer |
| 165 | spu_mfcdma32(buf[2], (unsigned int)fb, in_line_size, |
| 166 | tag_id_base + 3, MFC_PUTB_CMD); |
| 167 | in += in_line_stride; |
| 168 | fb += out_line_stride; |
| 169 | deprintf("[SPU] 3rd buffer copied in=0x%x, fb=0x%x\n", in, |
| 170 | fb); |
| 171 | |
| 172 | /* fourth buffer */ |
| 173 | DMA_WAIT_TAG(tag_id_base + 4); |
| 174 | // retrieve buffer |
| 175 | spu_mfcdma32(buf[3], (unsigned int)in, in_line_size, |
| 176 | tag_id_base + 4, MFC_GETB_CMD); |
| 177 | DMA_WAIT_TAG(tag_id_base + 4); |
| 178 | // store buffer |
| 179 | spu_mfcdma32(buf[3], (unsigned int)fb, in_line_size, |
| 180 | tag_id_base + 4, MFC_PUTB_CMD); |
| 181 | in += in_line_stride; |
| 182 | fb += out_line_stride; |
| 183 | deprintf("[SPU] 4th buffer copied in=0x%x, fb=0x%x\n", in, |
| 184 | fb); |
| 185 | deprintf("[SPU] Loop #%i, bounded_input_height=%i\n", i, |
| 186 | bounded_input_height >> 2); |
| 187 | } |
| 188 | DMA_WAIT_TAG(tag_id_base + 2); |
| 189 | DMA_WAIT_TAG(tag_id_base + 3); |
| 190 | DMA_WAIT_TAG(tag_id_base + 4); |
| 191 | } |
| 192 | |
| 193 | |