1 /*
2  * Copyright 2023 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "fsl_jpegdec.h"
8 
9 /*******************************************************************************
10  * Definitions
11  ******************************************************************************/
12 
13 /* Component ID definition, used by tools. */
14 #ifndef FSL_COMPONENT_ID
15 #define FSL_COMPONENT_ID "platform.drivers.jpegdec"
16 #endif
17 
18 #if defined(JPEGDEC_RSTS)
19 #define JPEGDEC_RESETS_ARRAY JPEGDEC_RSTS
20 #endif
21 
22 #define JPEG_SOF0_MARKER 0xC0UL
23 #define JPEG_SOF1_MARKER 0xC1UL
24 #define JPEG_GET_U16(p)  ((((uint16_t)(*(p))) << 8) + ((uint16_t)(*((p) + 1))))
25 
26 /*******************************************************************************
27  * Prototypes
28  ******************************************************************************/
29 /*!
30  * @brief Get the jpegdec instance from the peripheral base address.
31  *
32  * @param base JPEG decoder peripheral base address.
33  * @return JPEG decoder instance.
34  */
35 static uint32_t JPEGDEC_GetInstance(JPEG_DECODER_Type *base);
36 
37 /*******************************************************************************
38  * Variables
39  ******************************************************************************/
40 /* Array of JPEG decoder core peripheral base address. */
41 static JPEGDEC_Type *const s_jpegdecBases[] = JPEGDEC_BASE_PTRS;
42 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
43 /* Clock name of JPEG decoder. */
44 static const clock_ip_name_t s_jpegdecClock[] = JPEGDEC_CLOCKS;
45 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
46 /* Array of JPEG decoder peripheral resets. */
47 #if defined(JPEGDEC_RESETS_ARRAY)
48 /* Reset array */
49 static const reset_ip_name_t s_jpegdecResets[] = JPEGDEC_RESETS_ARRAY;
50 #endif
51 
52 /*******************************************************************************
53  * Codes
54  ******************************************************************************/
JPEGDEC_GetInstance(JPEG_DECODER_Type * base)55 static uint32_t JPEGDEC_GetInstance(JPEG_DECODER_Type *base)
56 {
57     uint32_t instance = 0U;
58 
59     /* Find the instance index from base address mappings. */
60     for (instance = 0; instance < ARRAY_SIZE(s_jpegdecBases); instance++)
61     {
62         if (MSDK_REG_SECURE_ADDR(s_jpegdecBases[instance]) == MSDK_REG_SECURE_ADDR(base->core))
63         {
64             break;
65         }
66     }
67 
68     assert(instance < ARRAY_SIZE(s_jpegdecBases));
69 
70     return instance;
71 }
72 
73 /*!
74  * brief Gets the default configuration for JPEG decoder.
75  *
76  * This function initializes the user configuration structure to default value. The default value are:
77  *
78  * Example:
79    code
80    config->endianMode = kJPEGDEC_LittleEndian;
81    config->slots      = 0xFU;
82    config->enable     = true;
83    config->enableLp   = false;
84    endcode
85  *
86  * param config Pointer to JPEG decoder configuration structure.
87  */
JPEGDEC_GetDefaultConfig(jpegdec_config_t * config)88 void JPEGDEC_GetDefaultConfig(jpegdec_config_t *config)
89 {
90     assert(NULL != config);
91 
92     /* Initializes the configure structure to zero. */
93     (void)memset(config, 0, sizeof(*config));
94 
95     /* Fill default configuration */
96     config->endianMode = kJPEGDEC_LittleEndian;
97     config->slots      = 0xFU; /* Enable all 4 slots. */
98     config->enable     = true;
99     config->enableLp   = false;
100 }
101 
102 /*!
103  * brief Initializes the JPEG decoder.
104  *
105  * The default configuration can be got by calling @ref JPEGDEC_GetDefaultConfig().
106  *
107  * param base JPEG decoder peripheral base address.
108  * param config Pointer to JPEG decoder configuration structure.
109  */
JPEGDEC_Init(JPEG_DECODER_Type * base,const jpegdec_config_t * config)110 void JPEGDEC_Init(JPEG_DECODER_Type *base, const jpegdec_config_t *config)
111 {
112     assert(NULL != config);
113 
114 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
115     /* Open clock gate. */
116     CLOCK_EnableClock(s_jpegdecClock[JPEGDEC_GetInstance(base)]);
117 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
118 
119 #if defined(JPEGDEC_RESETS_ARRAY)
120     RESET_ReleasePeripheralReset(s_jpegdecResets[JPEGDEC_GetInstance(base)]);
121 #endif
122 
123     JPEGDEC_Reset(base);
124 
125     JPEGDEC_EnableSlots(base, config->slots);
126     JPEGDEC_SetEndian(base, config->endianMode);
127     JPEGDEC_Enable(base, config->enable);
128     JPEGDEC_EnableLp(base, config->enableLp);
129 }
130 
131 /*!
132  * brief Deinitializes the JPEG decoder.
133  *
134  * param base JPEG decoder peripheral base address.
135  */
JPEGDEC_Deinit(JPEG_DECODER_Type * base)136 void JPEGDEC_Deinit(JPEG_DECODER_Type *base)
137 {
138     /* Disable the module. */
139     JPEGDEC_Enable(base, false);
140 
141 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
142     /* Disable clock gate. */
143     CLOCK_DisableClock(s_jpegdecClock[JPEGDEC_GetInstance(base)]);
144 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
145 }
146 
147 /*!
148  * brief Gets the current active slot
149  *
150  * param base JPEG decoder peripheral base address.
151  * param slot Pointer to the variable that stores the enabled slot.
152  * retval #kStatus_Success Successfully get the current active slot.
153  * retval #kStatus_Fail Current JPEG decoder is idle, no slot is active.
154  */
JPEGDEC_GetActiveSlot(JPEG_DECODER_Type * base,uint8_t * slot)155 status_t JPEGDEC_GetActiveSlot(JPEG_DECODER_Type *base, uint8_t *slot)
156 {
157     if ((base->wrapper->COM_STATUS & JPGDECWRP_COM_STATUS_DEC_ONGOING_MASK) != 0U)
158     {
159         *slot = (uint8_t)((base->wrapper->COM_STATUS & JPGDECWRP_COM_STATUS_CUR_SLOT_MASK) >>
160                           JPGDECWRP_COM_STATUS_CUR_SLOT_SHIFT);
161         return kStatus_Success;
162     }
163     else
164     {
165         return kStatus_Fail;
166     }
167 }
168 
169 /*!
170  * brief Sets the address and length of the JPEG image.
171  *
172  * param[out] config Decoder configuration.
173  * param data Start address of the buffer of the raw JPEG image, shall be 8-byte aligned.
174  * param length Size of the buffer.
175  */
JPEGDEC_SetJpegBuffer(jpegdec_decoder_config_t * config,uint8_t * buffer,size_t length)176 void JPEGDEC_SetJpegBuffer(jpegdec_decoder_config_t *config, uint8_t *buffer, size_t length)
177 {
178     assert(((uint32_t)buffer & 0xFU) == 0U); /* Has to be 16-byte aligned. */
179 
180     config->jpegBufAddr = (uint32_t)buffer;
181     config->jpegBufSize = JPEG_ALIGN_SIZE(length, 0x400U); /* Has to be integer times of 1K. */
182 }
183 
184 /*!
185  * brief Sets the address of the decoded data.
186  *
187  * param[out] config Decoder configuration.
188  * param imageData0 address of the output buffer0, shall be 16-byte aligned.
189  * param imageData1 address of the output buffer1, only used when output format is YUV420, shall be 16-byte aligned.
190  */
JPEGDEC_SetOutputBuffer(jpegdec_decoder_config_t * config,uint8_t * imageData0,uint8_t * imageData1)191 void JPEGDEC_SetOutputBuffer(jpegdec_decoder_config_t *config, uint8_t *imageData0, uint8_t *imageData1)
192 {
193     assert(imageData0 != NULL);
194     assert(((uint32_t)imageData0 & 0xFU) == 0U); /* Has to be 16-byte aligned. */
195     assert(((uint32_t)imageData1 & 0xFU) == 0U);
196 
197     config->outBufAddr0 = (uint32_t)imageData0;
198     config->outBufAddr1 = (uint32_t)imageData1;
199 }
200 
201 /*!
202  * brief Parses the JPEG header and stores the info in the decoder configuration structure.
203  *
204  * param[out] config Decoder configuration.
205  * retval kStatus_Success Header parsing success.
206  * retval kStatus_Fail JPEG header parsing failed due corrupted header.
207  * retval kStatus_JPEGDEC_NotSupported Header parsing failed due to the image pixel format is not supported
208    or image width/height is larger than 8k or image width/height is not 8-byte or 16-byte aligned.
209  */
JPEGDEC_ParseHeader(jpegdec_decoder_config_t * config)210 status_t JPEGDEC_ParseHeader(jpegdec_decoder_config_t *config)
211 {
212     status_t result = kStatus_Success;
213     /* Get the JPEG image buffer and length. */
214     uint8_t *imageBuf    = (uint8_t *)config->jpegBufAddr;
215     uint32_t imageLength = config->jpegBufSize;
216     uint16_t width, height;
217 
218     /* Find the SOF0 marker, SOF image info need at least 16 bytes. */
219     imageLength = config->jpegBufSize;
220     imageBuf    = (uint8_t *)config->jpegBufAddr;
221     while (imageLength-- > 16U)
222     {
223         if (*imageBuf++ == 0xFFU)
224         {
225             if ((*imageBuf == JPEG_SOF0_MARKER) || (*imageBuf == JPEG_SOF1_MARKER))
226             {
227                 imageBuf++;
228                 break;
229             }
230         }
231     }
232 
233     if (imageLength == 16U)
234     {
235         /* Can not find the SOF marker, return error. */
236         return kStatus_Fail;
237     }
238 
239     /* Get the pixel depth. */
240     if (imageBuf[2] == 8U)
241     {
242         config->pixelDepth = (uint32_t)kJPEGDEC_PixelDepth8Bit;
243     }
244     else if (imageBuf[2] == 12U)
245     {
246         config->pixelDepth = (uint32_t)kJPEGDEC_PixelDepth12Bit;
247     }
248     else
249     {
250         /* Undefined pixel depth, return error. */
251         return kStatus_Fail;
252     }
253 
254     /* Check component number. */
255     switch (imageBuf[7U])
256     {
257         case 1U:
258             config->pixelFormat = (uint32_t)kJPEGDEC_PixelFormatGray;
259             break;
260         case 3U:
261             /* Componnet ids are 0x1, 0x2 and 0x3 means YUV format. */
262             if ((imageBuf[8U] == 0x1U) && (imageBuf[11U] == 0x2U) && (imageBuf[14U] == 0x3U))
263             {
264                 /* UV component x/y sample points is 1/1. */
265                 if ((imageBuf[12U] == 0x11U) && (imageBuf[15U] == 0x11U))
266                 {
267                     /* Y component x/y sample points is also 1/1, means each Y component has 1 UV component, format
268                      * YUV444. */
269                     if (imageBuf[9U] == 0x11U)
270                     {
271                         config->pixelFormat = (uint32_t)kJPEGDEC_PixelFormatYUV444;
272                     }
273                     /* Y component x/y sample points is 2/1 or 1/2, means in each line/row every 2 Y componnets share 1
274                      * UV component, format YUV422. */
275                     else if ((imageBuf[9U] == 0x21U) || (imageBuf[9U] == 0x12U))
276                     {
277                         config->pixelFormat = (uint32_t)kJPEGDEC_PixelFormatYUV422;
278                     }
279                     /* Y component sample points is 2/2, means in each line and each column, every 2 Y componnets share
280                      * 1 U or V component, format YUV420. */
281                     else if (imageBuf[9U] == 0x22U)
282                     {
283                         config->pixelFormat = (uint32_t)kJPEGDEC_PixelFormatYUV420;
284                     }
285                     else
286                     {
287                         /* Unsupported pixel format. */
288                         return kStatus_JPEGDEC_NotSupported;
289                     }
290                 }
291                 else
292                 {
293                     /* Unsupported pixel format. */
294                     return kStatus_JPEGDEC_NotSupported;
295                 }
296             }
297             /* Componnet ids are 0x52, 0x47 and 0x42 means RGB format. */
298             else if ((imageBuf[8U] == 0x52U) && (imageBuf[11U] == 0x47U) && (imageBuf[14U] == 0x42U))
299             {
300                 /* Component ID = "RGB" */
301                 config->pixelFormat = (uint32_t)kJPEGDEC_PixelFormatRGB;
302             }
303             else
304             {
305                 /* Unsupported pixel format. */
306                 return kStatus_JPEGDEC_NotSupported;
307             }
308             break;
309         case 4U:
310             config->pixelFormat = (uint32_t)kJPEGDEC_PixelFormatYCCK;
311             break;
312         default:
313             /* Unknown component number, return error. */
314             result = kStatus_JPEGDEC_NotSupported;
315             break;
316     }
317 
318     if (result != kStatus_Success)
319     {
320         return result;
321     }
322 
323     /* Get the height and width. */
324     height = JPEG_GET_U16(&imageBuf[3]);
325     width  = JPEG_GET_U16(&imageBuf[5]);
326     if ((height > 0x2000U) || (width > 0x2000U) || (height < 64U) || (width < 64U))
327     {
328         /* Max support 8K width/height, min support 64 width/height. Picture with width/height that is
329            smaller than 64 will corrupt the next frame to be decoded. Errata ERR050135. */
330         return kStatus_JPEGDEC_NotSupported;
331     }
332 
333     config->height = (uint32_t)height;
334     config->width  = (uint32_t)width;
335 
336     if (config->pixelFormat == (uint32_t)kJPEGDEC_PixelFormatYUV420)
337     {
338         if (((height & 0xFU) != 0U) || ((width & 0xFU) != 0U))
339         {
340             result = kStatus_JPEGDEC_NotSupported;
341         }
342     }
343     else if (config->pixelFormat == (uint32_t)kJPEGDEC_PixelFormatYUV422)
344     {
345         /* For YUV422, width and height shall be divisible by 16 and 8. */
346         if (((height & 0x7U) != 0U) || ((width & 0xFU) != 0U))
347         {
348             result = kStatus_JPEGDEC_NotSupported;
349         }
350     }
351     else
352     {
353         /* For YUV420, width and height shall all be divisible by 8. */
354         if (((height & 0x7U) != 0U) || ((width & 0x7U) != 0U))
355         {
356             result = kStatus_JPEGDEC_NotSupported;
357         }
358     }
359 
360     return result;
361 }
362 
363 /*!
364  * brief Sets the decode option.
365  *
366  * param[out] config Decoder configuration.
367  * param pitch Output buffer pitch.
368  * param clearStreamBuf Set to true to clear the saved bit stream buffer, not used in single frame mode.
369  * param autoStart Set to true to automatically start the decoding when this descriptor is switched, not used in single
370    frame mode.
371  */
JPEGDEC_SetDecodeOption(jpegdec_decoder_config_t * config,uint16_t pitch,bool clearStreamBuf,bool autoStart)372 void JPEGDEC_SetDecodeOption(jpegdec_decoder_config_t *config, uint16_t pitch, bool clearStreamBuf, bool autoStart)
373 {
374     config->outBufPitch    = (uint32_t)pitch;
375     config->clearStreamBuf = (uint32_t)clearStreamBuf;
376     config->autoStart      = (uint32_t)autoStart;
377 }
378 
379 /*!
380  * brief Sets JPEG decoder decoder configuration.
381  *
382  * Call this API to set the decoder configuration and then call @ref JPEGDEC_StartDecode
383  * to start decode. Need to enable at least one slot in @ref jpegdec_config_t first.
384  *
385  * param base JPEG decoder peripheral base address.
386  * param config Decoder configuration.
387  */
JPEGDEC_ConfigDecoder(JPEG_DECODER_Type * base,const jpegdec_decoder_config_t * config)388 void JPEGDEC_ConfigDecoder(JPEG_DECODER_Type *base, const jpegdec_decoder_config_t *config)
389 {
390     assert((config->outBufAddr0 & 0xFU) == 0U);
391     assert((config->outBufAddr1 & 0xFU) == 0U);
392     assert((config->jpegBufAddr & 0xFU) == 0U);
393     assert((config->jpegBufSize & 0x3FFU) == 0U);
394 
395     base->wrapper->OUT_BUF_BASE0 = config->outBufAddr0;
396     base->wrapper->OUT_BUF_BASE1 = config->outBufAddr1;
397     base->wrapper->OUT_PITCH     = (uint32_t)config->outBufPitch;
398     base->wrapper->STM_BUFBASE   = config->jpegBufAddr;
399     base->wrapper->STM_BUFSIZE   = config->jpegBufSize;
400     base->wrapper->IMGSIZE       = (uint32_t)config->height | ((uint32_t)config->width << 16U);
401     base->wrapper->STM_CTRL      = (config->pixelDepth << JPGDECWRP_STM_CTRL_PIXEL_PRECISION_SHIFT) |
402                               (config->pixelFormat << JPGDECWRP_STM_CTRL_IMAGE_FORMAT_SHIFT) |
403                               (config->clearStreamBuf << JPGDECWRP_STM_CTRL_BITBUF_PTR_CLR_SHIFT) |
404                               (config->autoStart << JPGDECWRP_STM_CTRL_AUTO_START_SHIFT);
405 }
406 
407 /*!
408  * brief Sets the address of the next decoder descriptor for certain slot
409  *
410  * Call this API to set the decoder descriptor for certain slot, and then call
411  * @ref JPEGDEC_EnableSlotNextDescpt to enable the descriptor. If the decode configuration
412  * of this descriptor has enabled autoStart then decode will start automatically.
413  * Otherwise user has to call @ref JPEGDEC_StartDecode manually. Need to enable the
414  * slot in @ref jpegdec_config_t first.
415  *
416  * param base JPEG decoder peripheral base address.
417  * param slot Slot number.
418  * param descriptor Pointer to the descriptor structure.
419  */
JPEGDEC_SetSlotNextDescpt(JPEG_DECODER_Type * base,uint8_t slot,jpegdec_descpt_t * descriptor)420 void JPEGDEC_SetSlotNextDescpt(JPEG_DECODER_Type *base, uint8_t slot, jpegdec_descpt_t *descriptor)
421 {
422     assert(slot < 4U);
423     assert(((uint32_t)descriptor & 0x3U) == 0U);
424     assert((descriptor->config.outBufAddr0 & 0xFU) == 0U);
425     assert((descriptor->config.outBufAddr1 & 0xFU) == 0U);
426     assert((descriptor->config.jpegBufAddr & 0xFU) == 0U);
427     assert((descriptor->config.jpegBufSize & 0x3FFU) == 0U);
428 
429     base->wrapper->SLOT_REGS[slot].SLOT_NXT_DESCPT_PTR = (uint32_t)descriptor;
430 }
431 
432 /*!
433  * brief Sets all fields to default values for the descriptor structure.
434  *
435  * param descriptor Pointer to the descriptor structure.
436  * note This function enables the auto start feature.
437  */
JPEGDEC_DescptReset(jpegdec_descpt_t * descriptor)438 void JPEGDEC_DescptReset(jpegdec_descpt_t *descriptor)
439 {
440     assert(descriptor != NULL);
441 
442     /* Reset channel descriptor */
443     descriptor->nextDescptAddr        = 0U;
444     descriptor->config.outBufAddr0    = 0U;
445     descriptor->config.outBufAddr0    = 0U;
446     descriptor->config.outBufPitch    = 0U;
447     descriptor->config.jpegBufAddr    = 0U;
448     descriptor->config.jpegBufSize    = 0U;
449     descriptor->config.height         = 0U;
450     descriptor->config.width          = 0U;
451     descriptor->config.pixelDepth     = (uint32_t)kJPEGDEC_PixelDepth8Bit;
452     descriptor->config.pixelFormat    = (uint32_t)kJPEGDEC_PixelFormatYUV420;
453     descriptor->config.clearStreamBuf = (uint32_t) false;
454     /* Enable auto start. */
455     descriptor->config.autoStart = (uint32_t) true;
456 }
457