19682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
29682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * SDL - Simple DirectMedia Layer
39682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * CELL BE Support for PS3 Framebuffer
49682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * Copyright (C) 2008, 2009 International Business Machines Corporation
59682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *
69682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * This library is free software; you can redistribute it and/or modify it
79682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * under the terms of the GNU Lesser General Public License as published
89682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * by the Free Software Foundation; either version 2.1 of the License, or
99682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * (at your option) any later version.
109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *
119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * This library is distributed in the hope that it will be useful, but
129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * WITHOUT ANY WARRANTY; without even the implied warranty of
139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * Lesser General Public License for more details.
159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *
169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * You should have received a copy of the GNU Lesser General Public
179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * License along with this library; if not, write to the Free Software
189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * USA
209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *
219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *  Martin Lowinski  <lowinski [at] de [dot] ibm [ibm] com>
229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *  Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com>
239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *  SPE code based on research by:
249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *  Rene Becker
259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *  Thimo Emmerich
269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "spu_common.h"
299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <spu_intrinsics.h>
319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <spu_mfcio.h>
329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <stdio.h>
339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <string.h>
349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall// Debugging
369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall//#define DEBUG
379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef DEBUG
399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define deprintf(fmt, args... ) \
409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	fprintf( stdout, fmt, ##args ); \
419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	fflush( stdout );
429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else
439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define deprintf( fmt, args... )
449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid cpy_to_fb(unsigned int);
479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* fb_writer_spu parms */
499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic volatile struct fb_writer_parms_t parms __attribute__ ((aligned(128)));
509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Code running on SPU */
529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallint main(unsigned long long spe_id __attribute__ ((unused)), unsigned long long argp __attribute__ ((unused)))
539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	deprintf("[SPU] fb_writer_spu is up... (on SPE #%llu)\n", spe_id);
559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	uint32_t ea_mfc, mbox;
569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	// send ready message
579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	spu_write_out_mbox(SPU_READY);
589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	while (1) {
609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Check mailbox */
619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		mbox = spu_read_in_mbox();
629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		deprintf("[SPU] Message is %u\n", mbox);
639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		switch (mbox) {
649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			case SPU_EXIT:
659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				deprintf("[SPU] fb_writer goes down...\n");
669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				return 0;
679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			case SPU_START:
689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				break;
699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			default:
709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				deprintf("[SPU] Cannot handle message\n");
719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				continue;
729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Tag Manager setup */
759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		unsigned int tags;
769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		tags = mfc_multi_tag_reserve(5);
779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (tags == MFC_TAG_INVALID) {
789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			deprintf("[SPU] Failed to reserve mfc tags on fb_writer\n");
799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			return 0;
809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Framebuffer parms */
839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		ea_mfc = spu_read_in_mbox();
849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		deprintf("[SPU] Message on fb_writer is %u\n", ea_mfc);
859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		spu_mfcdma32(&parms, (unsigned int)ea_mfc,
869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				sizeof(struct fb_writer_parms_t), tags,
879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				MFC_GET_CMD);
889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		deprintf("[SPU] argp = %u\n", (unsigned int)argp);
899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		DMA_WAIT_TAG(tags);
909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Copy parms->data to framebuffer */
929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		deprintf("[SPU] Copying to framebuffer started\n");
939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		cpy_to_fb(tags);
949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		deprintf("[SPU] Copying to framebuffer done!\n");
959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		mfc_multi_tag_release(tags, 5);
979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		deprintf("[SPU] fb_writer_spu... done!\n");
989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Send FIN msg */
999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		spu_write_out_mbox(SPU_FIN);
1009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
1019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return 0;
1039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
1049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid cpy_to_fb(unsigned int tag_id_base)
1069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
1079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned int i;
1089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned char current_buf;
1099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	uint8_t *in = parms.data;
1109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Align fb pointer which was centered before */
1129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	uint8_t *fb =
1139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    (unsigned char *)((unsigned int)parms.center & 0xFFFFFFF0);
1149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	uint32_t bounded_input_height = parms.bounded_input_height;
1169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	uint32_t bounded_input_width = parms.bounded_input_width;
1179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	uint32_t fb_pixel_size = parms.fb_pixel_size;
1189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	uint32_t out_line_stride = parms.out_line_stride;
1209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	uint32_t in_line_stride = parms.in_line_stride;
1219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	uint32_t in_line_size = bounded_input_width * fb_pixel_size;
1229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	current_buf = 0;
1249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Local store buffer */
1269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	static volatile uint8_t buf[4][BUFFER_SIZE]
1279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    __attribute__ ((aligned(128)));
1289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* do 4-times multibuffering using DMA list, process in two steps */
1299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	for (i = 0; i < bounded_input_height >> 2; i++) {
1309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* first buffer */
1319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		DMA_WAIT_TAG(tag_id_base + 1);
1329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		// retrieve buffer
1339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		spu_mfcdma32(buf[0], (unsigned int)in, in_line_size,
1349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			     tag_id_base + 1, MFC_GETB_CMD);
1359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		DMA_WAIT_TAG(tag_id_base + 1);
1369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		// store buffer
1379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		spu_mfcdma32(buf[0], (unsigned int)fb, in_line_size,
1389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			     tag_id_base + 1, MFC_PUTB_CMD);
1399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		in += in_line_stride;
1409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		fb += out_line_stride;
1419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		deprintf("[SPU] 1st buffer copied in=0x%x, fb=0x%x\n", in,
1429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		       fb);
1439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* second buffer */
1459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		DMA_WAIT_TAG(tag_id_base + 2);
1469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		// retrieve buffer
1479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		spu_mfcdma32(buf[1], (unsigned int)in, in_line_size,
1489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			     tag_id_base + 2, MFC_GETB_CMD);
1499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		DMA_WAIT_TAG(tag_id_base + 2);
1509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		// store buffer
1519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		spu_mfcdma32(buf[1], (unsigned int)fb, in_line_size,
1529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			     tag_id_base + 2, MFC_PUTB_CMD);
1539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		in += in_line_stride;
1549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		fb += out_line_stride;
1559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		deprintf("[SPU] 2nd buffer copied in=0x%x, fb=0x%x\n", in,
1569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		       fb);
1579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* third buffer */
1599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		DMA_WAIT_TAG(tag_id_base + 3);
1609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		// retrieve buffer
1619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		spu_mfcdma32(buf[2], (unsigned int)in, in_line_size,
1629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			     tag_id_base + 3, MFC_GETB_CMD);
1639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		DMA_WAIT_TAG(tag_id_base + 3);
1649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		// store buffer
1659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		spu_mfcdma32(buf[2], (unsigned int)fb, in_line_size,
1669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			     tag_id_base + 3, MFC_PUTB_CMD);
1679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		in += in_line_stride;
1689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		fb += out_line_stride;
1699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		deprintf("[SPU] 3rd buffer copied in=0x%x, fb=0x%x\n", in,
1709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		       fb);
1719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* fourth buffer */
1739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		DMA_WAIT_TAG(tag_id_base + 4);
1749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		// retrieve buffer
1759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		spu_mfcdma32(buf[3], (unsigned int)in, in_line_size,
1769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			     tag_id_base + 4, MFC_GETB_CMD);
1779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		DMA_WAIT_TAG(tag_id_base + 4);
1789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		// store buffer
1799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		spu_mfcdma32(buf[3], (unsigned int)fb, in_line_size,
1809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			     tag_id_base + 4, MFC_PUTB_CMD);
1819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		in += in_line_stride;
1829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		fb += out_line_stride;
1839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		deprintf("[SPU] 4th buffer copied in=0x%x, fb=0x%x\n", in,
1849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		       fb);
1859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		deprintf("[SPU] Loop #%i, bounded_input_height=%i\n", i,
1869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		       bounded_input_height >> 2);
1879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
1889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	DMA_WAIT_TAG(tag_id_base + 2);
1899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	DMA_WAIT_TAG(tag_id_base + 3);
1909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	DMA_WAIT_TAG(tag_id_base + 4);
1919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
1929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
194