1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - dsp
3   File:     dsp_graphics.c
4 
5   Copyright 2008 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-03-02#$
14   $Rev: 10122 $
15   $Author: kitase_hirotake $
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 /*---------------------------------------------------------------------------*/
35 /* Functions */
36 
37 /*---------------------------------------------------------------------------*
38   Name:         DSPi_OpenStaticComponentGraphicsCore
39 
40   Description:  Opens the memory file for the graphics component.
41                 It is no longer necessary to prepare a file system in advance. Because it is linked as static memory, the program size increases.
42 
43 
44   Arguments:    file: FSFile structure that opens the memory file
45 
46   Returns:      None.
47  *---------------------------------------------------------------------------*/
DSPi_OpenStaticComponentGraphicsCore(FSFile * file)48 void DSPi_OpenStaticComponentGraphicsCore(FSFile *file)
49 {
50     extern const u8 DSPiFirmware_graphics[];
51     (void)DSPi_CreateMemoryFile(file, DSPiFirmware_graphics);
52 }
53 
54 /*---------------------------------------------------------------------------*
55   Name:         DSPi_GraphicsEvents(viod *userdata)
56 
57   Description:  Event handler of the DSP graphics component.
58 
59   Arguments:    None.
60 
61   Returns:      None.
62  *---------------------------------------------------------------------------*/
DSPi_GraphicsEvents(void * userdata)63 static void DSPi_GraphicsEvents(void *userdata)
64 {
65     (void)userdata;
66 
67     // When running asynchronous processing, check the presence of end notices
68     if ( isAsync )
69     {
70         replyReg = DSP_RecvData(DSP_GRAPHICS_REP_REGISTER);
71         if (replyReg == DSP_STATE_SUCCESS)
72         {
73             isBusy = FALSE;
74             isAsync = FALSE;
75 
76             if ( callBackFunc != NULL)
77             {
78                 callBackFunc();
79             }
80         }
81         else if (replyReg == DSP_STATE_FAIL)
82         {
83             OS_Warning("a process on DSP is failed.\n");
84             isBusy = FALSE;
85             isAsync = FALSE;
86         }
87         else
88         {
89             OS_Warning("unknown error occured.\n");
90             isBusy = FALSE;
91             isAsync = FALSE;
92         }
93     }
94     else    // Synchronous version
95     {
96 //        replyReg = DSP_RecvData(DSP_GRAPHICS_REP_REGISTER);
97 //        isBusy = FALSE;
98     }
99 }
100 
101 /*---------------------------------------------------------------------------*
102   Name:         DSP_LoadGraphicsCore
103 
104   Description:  Loads graphics component to DSP.
105 
106   Arguments:    file: Graphics component file
107                 slotB: WRAM-B allowed for use for code memory
108                 slotC: WRAM-C allowed for use for data memory
109 
110   Returns:      TRUE if the graphics component is correctly loaded to DSP.
111  *---------------------------------------------------------------------------*/
DSPi_LoadGraphicsCore(FSFile * file,int slotB,int slotC)112 BOOL DSPi_LoadGraphicsCore(FSFile *file, int slotB, int slotC)
113 {
114     if (!DSPiGraphicsAvailable)
115     {
116         isBusy = FALSE;
117         isAsync = FALSE;
118         DSP_InitProcessContext(DSPiProcessGraphics, "graphics");
119         // (If there is specification to a linker script file on the DSP side, this explicit setting is unnecessary)
120         DSPiProcessGraphics->flags |= DSP_PROCESS_FLAG_USING_OS;
121         DSP_SetProcessHook(DSPiProcessGraphics,
122                            DSP_HOOK_REPLY_(DSP_GRAPHICS_REP_REGISTER),
123                            DSPi_GraphicsEvents, NULL);
124         if (DSP_ExecuteProcess(DSPiProcessGraphics, file, slotB, slotC))
125         {
126             DSPiGraphicsAvailable = TRUE;
127         }
128 
129         (void)DSP_LoadPipe(binOut, DSP_PIPE_BINARY, DSP_PIPE_OUTPUT);
130     }
131 
132     return DSPiGraphicsAvailable;
133 }
134 
135 /*---------------------------------------------------------------------------*
136   Name:         DSP_UnloadGraphicsCore
137 
138   Description:  Ends the DSP graphics component.
139 
140   Arguments:    None.
141 
142   Returns:      None.
143  *---------------------------------------------------------------------------*/
DSPi_UnloadGraphicsCore(void)144 void DSPi_UnloadGraphicsCore(void)
145 {
146     if(DSPiGraphicsAvailable)
147     {
148         DSP_QuitProcess(DSPiProcessGraphics);
149         DSPiGraphicsAvailable = FALSE;
150     }
151 }
152 
153 /*---------------------------------------------------------------------------*
154   Name:         DSPi_YuvToRgbConvertCore
155 
156   Description:  Converts YUV to RGB.
157 
158   Arguments:    src: Processing origin data address
159                 dest: Address for storing data (destination) after processing
160                 size: src data size
161                 callback: Pointer for callback function run after conversion ends
162                 async: TRUE when running asynchronously
163 
164   Returns:      TRUE if successful.
165  *---------------------------------------------------------------------------*/
DSPi_ConvertYuvToRgbCore(const void * src,void * dst,u32 size,DSP_GraphicsCallback callback,BOOL async)166 BOOL DSPi_ConvertYuvToRgbCore(const void* src, void* dst, u32 size, DSP_GraphicsCallback callback, BOOL async)
167 {
168     DSPYuv2RgbParam yr_param;
169     u32 offset = 0;
170     u16 command;
171 
172     // Check one more time whether DSP is busy
173     if (isBusy)
174     {
175         OS_TPrintf("dsp is busy.\n");
176         return FALSE;
177     }
178     isBusy = TRUE;
179 
180     // Register the callback function
181     callBackFunc = callback;
182     isAsync = async;
183 
184     if (async)
185     {
186         DSP_SetProcessHook(DSPiProcessGraphics,
187                            DSP_HOOK_REPLY_(DSP_GRAPHICS_REP_REGISTER),
188                            DSPi_GraphicsEvents, NULL);
189     }
190     else
191     {
192         DSP_SetProcessHook(DSPiProcessGraphics,
193                            DSP_HOOK_REPLY_(DSP_GRAPHICS_REP_REGISTER),
194                            NULL, NULL);
195     }
196 
197     // Notify the content of processes to start to DSP
198     command = DSP_G_FUNCID_YUV2RGB;
199     DSP_SendData(DSP_GRAPHICS_COM_REGISTER, command);
200 
201     // Parameter transmission to DSP
202     yr_param.size = size;
203     yr_param.src = (u32)((u32)src + offset);
204     yr_param.dst = (u32)((u32)dst + offset);
205 
206     DSP_WritePipe(binOut, &yr_param, sizeof(DSPYuv2RgbParam));
207 
208     if (async)
209     {
210         return TRUE;
211     }
212     else
213     {
214         // Wait for a reply from the DSP
215         while (!DSP_RecvDataIsReady(DSP_GRAPHICS_REP_REGISTER)) {
216             OS_Sleep(1);
217         }
218         replyReg = DSP_RecvData(DSP_GRAPHICS_REP_REGISTER);
219         isBusy = FALSE;
220 
221         if ( replyReg == DSP_STATE_SUCCESS)
222         {
223             return TRUE;
224         }
225         else
226         {
227             return FALSE;
228         }
229     }
230 
231     return FALSE;
232 }
233 
234 /*---------------------------------------------------------------------------*
235   Name:         DSPi_ScalingCore
236 
237   Description:  Scales the image data.
238 
239   Returns:      TRUE if successful.
240  *---------------------------------------------------------------------------*/
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)241 BOOL DSPi_ScalingCore(const void* src, void* dst, u16 img_width, u16 img_height, f32 rx, f32 ry, DSPGraphicsScalingMode mode,
242                       u16 x, u16 y, u16 width, u16 height, DSP_GraphicsCallback callback, BOOL async)
243 {
244     DSPScalingParam sc_param;
245 
246     u16 command;
247 
248     // Check one more time whether DSP is busy
249     if (isBusy)
250     {
251         OS_TPrintf("dsp is busy.\n");
252         return FALSE;
253     }
254     isBusy = TRUE;
255 
256     // Register the callback function
257     callBackFunc = callback;
258     isAsync = async;
259     if (async)
260     {
261         DSP_SetProcessHook(DSPiProcessGraphics,
262                            DSP_HOOK_REPLY_(DSP_GRAPHICS_REP_REGISTER),
263                            DSPi_GraphicsEvents, NULL);
264     }
265     else
266     {
267         DSP_SetProcessHook(DSPiProcessGraphics,
268                            DSP_HOOK_REPLY_(DSP_GRAPHICS_REP_REGISTER),
269                            NULL, NULL);
270     }
271 
272     // Notify the content of processes to start to DSP
273     command = DSP_G_FUNCID_SCALING;
274     DSP_SendData(DSP_GRAPHICS_COM_REGISTER, command);
275 
276     // Transfer parameters to DSP
277     sc_param.src = (u32)src;
278     sc_param.dst = (u32)dst;
279     sc_param.mode = mode;
280     sc_param.img_width = img_width;
281     sc_param.img_height = img_height;
282     sc_param.rate_w = (u16)(rx * 1000);
283     sc_param.rate_h = (u16)(ry * 1000);
284     sc_param.block_x = x;
285     sc_param.block_y = y;
286     sc_param.width = width;
287     sc_param.height = height;
288 
289     DSP_WritePipe(binOut, &sc_param, sizeof(DSPScalingParam));
290 
291     // Branch if running asynchronously
292     if(isAsync)
293     {
294         return TRUE;
295     }
296     else
297     {
298         // Wait for a reply from the DSP
299         while (!DSP_RecvDataIsReady(DSP_GRAPHICS_REP_REGISTER)) {
300             OS_Sleep(1);
301         }
302 
303         replyReg = DSP_RecvData(DSP_GRAPHICS_REP_REGISTER);
304         isBusy = FALSE;
305 
306         if ( replyReg == DSP_STATE_SUCCESS )
307         {
308             return TRUE;
309         }
310         else
311         {
312             return FALSE;
313         }
314     }
315 
316     return FALSE;
317 }
318 
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)319 BOOL DSPi_ScalingFxCore(const void* src, void* dst, u16 img_width, u16 img_height, fx32 rx, fx32 ry, DSPGraphicsScalingMode mode,
320                       u16 x, u16 y, u16 width, u16 height, DSP_GraphicsCallback callback, BOOL async)
321 {
322     DSPScalingParam sc_param;
323 
324     u16 command;
325 
326     // Check one more time whether DSP is busy
327     if (isBusy)
328     {
329         OS_TPrintf("dsp is busy.\n");
330         return FALSE;
331     }
332     isBusy = TRUE;
333 
334     // Register the callback function
335     callBackFunc = callback;
336     isAsync = async;
337 
338     if (async)
339     {
340         DSP_SetProcessHook(DSPiProcessGraphics,
341                            DSP_HOOK_REPLY_(DSP_GRAPHICS_REP_REGISTER),
342                            DSPi_GraphicsEvents, NULL);
343     }
344     else
345     {
346         DSP_SetProcessHook(DSPiProcessGraphics,
347                            DSP_HOOK_REPLY_(DSP_GRAPHICS_REP_REGISTER),
348                            NULL, NULL);
349     }
350 
351     // Notify the content of processes to start to DSP
352     command = DSP_G_FUNCID_SCALING;
353     DSP_SendData(DSP_GRAPHICS_COM_REGISTER, command);
354 
355     // Transfer parameters to DSP
356     sc_param.src = (u32)src;
357     sc_param.dst = (u32)dst;
358     sc_param.mode = mode;
359     sc_param.img_width = img_width;
360     sc_param.img_height = img_height;
361     sc_param.rate_w = (u16)(rx / 4096.0f * 1000);
362     sc_param.rate_h = (u16)(ry / 4096.0f * 1000);
363     sc_param.block_x = x;
364     sc_param.block_y = y;
365     sc_param.width = width;
366     sc_param.height = height;
367 
368     DSP_WritePipe(binOut, &sc_param, sizeof(DSPScalingParam));
369 
370     // Branch if running asynchronously
371     if(isAsync)
372     {
373         return TRUE;
374     }
375     else
376     {
377         // Wait for a reply from the DSP
378         while (!DSP_RecvDataIsReady(DSP_GRAPHICS_REP_REGISTER)) {
379             OS_Sleep(1);
380         }
381         replyReg = DSP_RecvData(DSP_GRAPHICS_REP_REGISTER);
382         isBusy = FALSE;
383 
384         if ( replyReg == DSP_STATE_SUCCESS )
385         {
386             return TRUE;
387         }
388         else
389         {
390             return FALSE;
391         }
392     }
393 
394     return FALSE;
395 }
396 
397