Home | History | Annotate | Download | only in spulibs
      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 
    194