1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - dsp
3   File:     dsp_graphics.c
4 
5   Copyright 2008-2009 Nintendo.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Date:: 2009-06-19#$
14   $Rev: 10786 $
15   $Author: okajima_manabu $
16  *---------------------------------------------------------------------------*/
17 #include <twl.h>
18 #include <twl/dsp.h>
19 #include <twl/dsp/common/graphics.h>
20 
21 #include "dsp_process.h"
22 
23 extern const u8 DSPiFirmware_graphics[];
24 
25 /*---------------------------------------------------------------------------*/
26 /* Variables */
27 
28 static DSPPipe binOut[1];
29 static BOOL DSPiGraphicsAvailable = FALSE;
30 static DSPProcessContext DSPiProcessGraphics[1];
31 
32 static u16 replyReg;
33 
34 /* Determine whether limitation conditions have been met (FALSE if so) */
35 static BOOL CheckLimitation(f32 rx, f32 ry, DSPGraphicsScalingMode mode, u16 src_width);
36 
37 /*---------------------------------------------------------------------------*/
38 /* Functions */
39 /*---------------------------------------------------------------------------*
40   Name:         CheckLimitation
41 
42   Description:  Determines if limitation conditions set by the DSP_Scaling* functions' specifications have been met.
43 
44   Arguments:    mode: Scaling mode
45                 rx, ry: Horizontal and vertical scaling factors
46                 src_width: Width of the input image
47 
48   Returns:      FALSE if limitation conditions have been met
49  *---------------------------------------------------------------------------*/
CheckLimitation(f32 rx,f32 ry,DSPGraphicsScalingMode mode,u16 src_width)50 static BOOL CheckLimitation(f32 rx, f32 ry, DSPGraphicsScalingMode mode, u16 src_width)
51 {
52     // When the processed data size is at least as large as the original data size
53     if (rx * ry >= 1.0f)
54     {
55         switch(mode)
56         {
57         case DSP_GRAPHICS_SCALING_MODE_N_NEIGHBOR:
58         case DSP_GRAPHICS_SCALING_MODE_BILINEAR:
59             if (DSP_CALC_SCALING_SIZE(src_width, rx) * ry >= 8192)
60             {
61                 return FALSE;
62             }
63             break;
64         case DSP_GRAPHICS_SCALING_MODE_BICUBIC:
65             if (DSP_CALC_SCALING_SIZE(src_width, rx) * ry >= 4096)
66             {
67                 return FALSE;
68             }
69             break;
70         }
71     }
72     else    // When the processed data size is less than the original data size
73     {
74         switch(mode)
75         {
76         case DSP_GRAPHICS_SCALING_MODE_N_NEIGHBOR:
77         case DSP_GRAPHICS_SCALING_MODE_BILINEAR:
78             if (src_width >= 8192)
79             {
80                 return FALSE;
81             }
82             break;
83         case DSP_GRAPHICS_SCALING_MODE_BICUBIC:
84             if (src_width >= 4096)
85             {
86                 return FALSE;
87             }
88             break;
89         }
90     }
91     return TRUE;
92 }
93 
94 /*---------------------------------------------------------------------------*
95   Name:         DSPi_OpenStaticComponentGraphicsCore
96 
97   Description:  Opens the memory file(s) for the graphics component.
98                 It is no longer necessary to prepare a file system in advance, but because it is linked as static memory, the program size increases.
99 
100 
101   Arguments:    file: FSFile structure that opens the memory file
102 
103   Returns:      None.
104  *---------------------------------------------------------------------------*/
DSPi_OpenStaticComponentGraphicsCore(FSFile * file)105 void DSPi_OpenStaticComponentGraphicsCore(FSFile *file)
106 {
107     extern const u8 DSPiFirmware_graphics[];
108     (void)DSPi_CreateMemoryFile(file, DSPiFirmware_graphics);
109 }
110 
111 /*---------------------------------------------------------------------------*
112   Name:         DSPi_GraphicsEvents(void *userdata)
113 
114   Description:  Event handler of the DSP graphics component.
115 
116   Arguments:    None.
117 
118   Returns:      None.
119  *---------------------------------------------------------------------------*/
DSPi_GraphicsEvents(void * userdata)120 static void DSPi_GraphicsEvents(void *userdata)
121 {
122     (void)userdata;
123 
124     // When running asynchronous processing, check for the presence of completion notices
125     if ( isAsync )
126     {
127         replyReg = DSP_RecvData(DSP_GRAPHICS_REP_REGISTER);
128         if (replyReg == DSP_STATE_SUCCESS)
129         {
130             isBusy = FALSE;
131             isAsync = FALSE;
132 
133             if ( callBackFunc != NULL)
134             {
135                 callBackFunc();
136             }
137         }
138         else if (replyReg == DSP_STATE_FAIL)
139         {
140             OS_TWarning("a process on DSP is failed.\n");
141             isBusy = FALSE;
142             isAsync = FALSE;
143         }
144         else
145         {
146             OS_TWarning("unknown error occured.\n");
147             isBusy = FALSE;
148             isAsync = FALSE;
149         }
150     }
151     else    // Synchronous version
152     {
153 //        replyReg = DSP_RecvData(DSP_GRAPHICS_REP_REGISTER);
154 //        isBusy = FALSE;
155     }
156 }
157 
158 /*---------------------------------------------------------------------------*
159   Name:         DSP_LoadGraphicsCore
160 
161   Description:  Loads graphics component to DSP.
162 
163   Arguments:    file: Graphics component file
164                 slotB: WRAM-B allowed for use for code memory
165                 slotC: WRAM-C allowed for use for data memory
166 
167   Returns:      TRUE if the graphics component is correctly loaded to DSP.
168  *---------------------------------------------------------------------------*/
DSPi_LoadGraphicsCore(FSFile * file,int slotB,int slotC)169 BOOL DSPi_LoadGraphicsCore(FSFile *file, int slotB, int slotC)
170 {
171     if (!DSPiGraphicsAvailable)
172     {
173         isBusy = FALSE;
174         isAsync = FALSE;
175         DSP_InitProcessContext(DSPiProcessGraphics, "graphics");
176         // (If there is specification to a linker script file on the DSP side, this explicit setting is unnecessary)
177         DSPiProcessGraphics->flags |= DSP_PROCESS_FLAG_USING_OS;
178         DSP_SetProcessHook(DSPiProcessGraphics,
179                            DSP_HOOK_REPLY_(DSP_GRAPHICS_REP_REGISTER),
180                            DSPi_GraphicsEvents, NULL);
181         if (DSP_ExecuteProcess(DSPiProcessGraphics, file, slotB, slotC))
182         {
183             DSPiGraphicsAvailable = TRUE;
184         }
185 
186         (void)DSP_LoadPipe(binOut, DSP_PIPE_BINARY, DSP_PIPE_OUTPUT);
187     }
188 
189     return DSPiGraphicsAvailable;
190 }
191 
192 /*---------------------------------------------------------------------------*
193   Name:         DSP_UnloadGraphicsCore
194 
195   Description:  Ends the DSP graphics component.
196 
197   Arguments:    None.
198 
199   Returns:      None.
200  *---------------------------------------------------------------------------*/
DSPi_UnloadGraphicsCore(void)201 void DSPi_UnloadGraphicsCore(void)
202 {
203     if(DSPiGraphicsAvailable)
204     {
205         DSP_QuitProcess(DSPiProcessGraphics);
206         DSPiGraphicsAvailable = FALSE;
207     }
208 }
209 
210 /*---------------------------------------------------------------------------*
211   Name:         DSPi_YuvToRgbConvertCore
212 
213   Description:  Converts YUV to RGB.
214 
215   Arguments:    src: Address of (source) data to process
216                 dest: Address for storing data (destination) after processing
217                 size: Size of src data
218                 callback: Pointer for callback function run after conversion ends
219                 async: TRUE when running asynchronously
220 
221   Returns:      TRUE if successful.
222  *---------------------------------------------------------------------------*/
DSPi_ConvertYuvToRgbCore(const void * src,void * dst,u32 size,DSP_GraphicsCallback callback,BOOL async)223 BOOL DSPi_ConvertYuvToRgbCore(const void* src, void* dst, u32 size, DSP_GraphicsCallback callback, BOOL async)
224 {
225     DSPYuv2RgbParam yr_param;
226     u32 offset = 0;
227     u16 command;
228 
229     // Check one more time whether DSP is busy
230     if (isBusy)
231     {
232         OS_TPrintf("dsp is busy.\n");
233         return FALSE;
234     }
235     isBusy = TRUE;
236 
237     // Register the callback function
238     callBackFunc = callback;
239     isAsync = async;
240 
241     if (async)
242     {
243         DSP_SetProcessHook(DSPiProcessGraphics,
244                            DSP_HOOK_REPLY_(DSP_GRAPHICS_REP_REGISTER),
245                            DSPi_GraphicsEvents, NULL);
246     }
247     else
248     {
249         DSP_SetProcessHook(DSPiProcessGraphics,
250                            DSP_HOOK_REPLY_(DSP_GRAPHICS_REP_REGISTER),
251                            NULL, NULL);
252     }
253 
254     // Notify the DSP of the content of processes to start
255     command = DSP_G_FUNCID_YUV2RGB;
256     DSP_SendData(DSP_GRAPHICS_COM_REGISTER, command);
257 
258     // Send parameters to DSP
259     yr_param.size = size;
260     yr_param.src = (u32)((u32)src + offset);
261     yr_param.dst = (u32)((u32)dst + offset);
262 
263     DSP_WritePipe(binOut, &yr_param, sizeof(DSPYuv2RgbParam));
264 
265     if (async)
266     {
267         return TRUE;
268     }
269     else
270     {
271         // Wait for a reply from the DSP
272         while (!DSP_RecvDataIsReady(DSP_GRAPHICS_REP_REGISTER)) {
273             OS_Sleep(1);
274         }
275         replyReg = DSP_RecvData(DSP_GRAPHICS_REP_REGISTER);
276         isBusy = FALSE;
277 
278         if ( replyReg == DSP_STATE_SUCCESS)
279         {
280             return TRUE;
281         }
282         else
283         {
284             return FALSE;
285         }
286     }
287 
288     return FALSE;
289 }
290 
291 /*---------------------------------------------------------------------------*
292   Name:         DSPi_ScalingCore
293 
294   Description:  Scales the image data.
295 
296   Returns:      TRUE if successful.
297  *---------------------------------------------------------------------------*/
DSPi_ScalingCore(const void * src,void * dst,u16 img_width,u16 img_height,f32 rx,f32 ry,DSPGraphicsScalingMode mode,u16 x,u16 y,u16 width,u16 height,DSP_GraphicsCallback callback,BOOL async)298 BOOL DSPi_ScalingCore(const void* src, void* dst, u16 img_width, u16 img_height, f32 rx, f32 ry, DSPGraphicsScalingMode mode,
299                       u16 x, u16 y, u16 width, u16 height, DSP_GraphicsCallback callback, BOOL async)
300 {
301     DSPScalingParam sc_param;
302 
303     u16 command;
304 
305     // Check limitation conditions
306     SDK_TASSERTMSG(CheckLimitation(rx, ry, mode, width), "DSP_Scaling: arguments exceed the limit.");
307 
308     // Check one more time whether DSP is busy
309     if (isBusy)
310     {
311         OS_TPrintf("dsp is busy.\n");
312         return FALSE;
313     }
314     isBusy = TRUE;
315 
316     // Register the callback function
317     callBackFunc = callback;
318     isAsync = async;
319     if (async)
320     {
321         DSP_SetProcessHook(DSPiProcessGraphics,
322                            DSP_HOOK_REPLY_(DSP_GRAPHICS_REP_REGISTER),
323                            DSPi_GraphicsEvents, NULL);
324     }
325     else
326     {
327         DSP_SetProcessHook(DSPiProcessGraphics,
328                            DSP_HOOK_REPLY_(DSP_GRAPHICS_REP_REGISTER),
329                            NULL, NULL);
330     }
331 
332     // Notify the DSP of the content of processes to start
333     command = DSP_G_FUNCID_SCALING;
334     DSP_SendData(DSP_GRAPHICS_COM_REGISTER, command);
335 
336     // Transfer parameters to DSP
337     sc_param.src = (u32)src;
338     sc_param.dst = (u32)dst;
339     sc_param.mode = mode;
340     sc_param.img_width = img_width;
341     sc_param.img_height = img_height;
342     sc_param.rate_w = (u16)(rx * 1000);
343     sc_param.rate_h = (u16)(ry * 1000);
344     sc_param.block_x = x;
345     sc_param.block_y = y;
346     sc_param.width = width;
347     sc_param.height = height;
348 
349     DSP_WritePipe(binOut, &sc_param, sizeof(DSPScalingParam));
350 
351     // Branch if processing asynchronously
352     if(isAsync)
353     {
354         return TRUE;
355     }
356     else
357     {
358         // Wait for a reply from the DSP
359         while (!DSP_RecvDataIsReady(DSP_GRAPHICS_REP_REGISTER)) {
360             OS_Sleep(1);
361         }
362 
363         replyReg = DSP_RecvData(DSP_GRAPHICS_REP_REGISTER);
364         isBusy = FALSE;
365 
366         if ( replyReg == DSP_STATE_SUCCESS )
367         {
368             return TRUE;
369         }
370         else
371         {
372             return FALSE;
373         }
374     }
375 
376     return FALSE;
377 }
378 
DSPi_ScalingFxCore(const void * src,void * dst,u16 img_width,u16 img_height,fx32 rx,fx32 ry,DSPGraphicsScalingMode mode,u16 x,u16 y,u16 width,u16 height,DSP_GraphicsCallback callback,BOOL async)379 BOOL DSPi_ScalingFxCore(const void* src, void* dst, u16 img_width, u16 img_height, fx32 rx, fx32 ry, DSPGraphicsScalingMode mode,
380                       u16 x, u16 y, u16 width, u16 height, DSP_GraphicsCallback callback, BOOL async)
381 {
382     DSPScalingParam sc_param;
383 
384     u16 command;
385 
386     // Check limitation conditions
387     SDK_TASSERTMSG(CheckLimitation(FX_FX32_TO_F32(rx), FX_FX32_TO_F32(ry), mode, width), "DSP_Scaling: arguments exceed the limit.");
388 
389     // Check one more time whether DSP is busy
390     if (isBusy)
391     {
392         OS_TPrintf("dsp is busy.\n");
393         return FALSE;
394     }
395     isBusy = TRUE;
396 
397     // Register the callback function
398     callBackFunc = callback;
399     isAsync = async;
400 
401     if (async)
402     {
403         DSP_SetProcessHook(DSPiProcessGraphics,
404                            DSP_HOOK_REPLY_(DSP_GRAPHICS_REP_REGISTER),
405                            DSPi_GraphicsEvents, NULL);
406     }
407     else
408     {
409         DSP_SetProcessHook(DSPiProcessGraphics,
410                            DSP_HOOK_REPLY_(DSP_GRAPHICS_REP_REGISTER),
411                            NULL, NULL);
412     }
413 
414     // Notify the DSP of the content of processes to start
415     command = DSP_G_FUNCID_SCALING;
416     DSP_SendData(DSP_GRAPHICS_COM_REGISTER, command);
417 
418     // Transfer parameters to DSP
419     sc_param.src = (u32)src;
420     sc_param.dst = (u32)dst;
421     sc_param.mode = mode;
422     sc_param.img_width = img_width;
423     sc_param.img_height = img_height;
424     sc_param.rate_w = (u16)(rx / 4096.0f * 1000);
425     sc_param.rate_h = (u16)(ry / 4096.0f * 1000);
426     sc_param.block_x = x;
427     sc_param.block_y = y;
428     sc_param.width = width;
429     sc_param.height = height;
430 
431     DSP_WritePipe(binOut, &sc_param, sizeof(DSPScalingParam));
432 
433     // Branch if processing asynchronously
434     if(isAsync)
435     {
436         return TRUE;
437     }
438     else
439     {
440         // Wait for a reply from the DSP
441         while (!DSP_RecvDataIsReady(DSP_GRAPHICS_REP_REGISTER)) {
442             OS_Sleep(1);
443         }
444         replyReg = DSP_RecvData(DSP_GRAPHICS_REP_REGISTER);
445         isBusy = FALSE;
446 
447         if ( replyReg == DSP_STATE_SUCCESS )
448         {
449             return TRUE;
450         }
451         else
452         {
453             return FALSE;
454         }
455     }
456 
457     return FALSE;
458 }
459 
460