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