• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include "hpm_jpeg_drv.h"
9 
10 #define HPM_JPEG_DEFAULT_MAX_OT (2)
11 
12 const jpeg_sampling_t jpeg_supported_sampling[5] = {
13     {2, 2, 1, 1}, /* 420 */
14     {2, 1, 1, 1}, /* 422H */
15     {1, 2, 1, 1}, /* 422V */
16     {1, 1, 1, 1}, /* 444 */
17     {1, 1, 0, 0}, /* 400 */
18 };
19 
20 const jpeg_pixel_t jpeg_supported_pixel_format[6] = {
21     {4, 1, 1, true}, /* JPEG_PIXEL_FORMAT_ARGB8888 */
22     {2, 2, 2, true}, /* JPEG_PIXEL_FORMAT_RGB565 */
23     {2, 3, 0, false}, /* JPEG_PIXEL_FORMAT_YUV422H1P */
24     {1, 0, 0, false}, /* JPEG_PIXEL_FORMAT_YUV422H2P */
25     {1, 0, 0, false}, /* JPEG_PIXEL_FORMAT_YUV420 */
26     {1, 0, 0, false}, /* JPEG_PIXEL_FORMAT_Y8 */
27 };
28 
jpeg_disable_irq(JPEG_Type * ptr,uint32_t mask)29 void jpeg_disable_irq(JPEG_Type *ptr, uint32_t mask)
30 {
31     if (mask & JPEG_EVENT_IN_DMA_FINISH) {
32         ptr->INDMA_MISC &= ~(JPEG_INDMA_MISC_IN_DMA_DONE_IRQ_EN_MASK
33             | JPEG_INDMA_MISC_IRQ_EN_MASK);
34     }
35     if (mask & JPEG_EVENT_OUT_DMA_FINISH) {
36         ptr->OUTDMA_MISC &= ~(JPEG_OUTDMA_MISC_OUT_DMA_DONE_IRQ_EN_MASK
37             | JPEG_OUTDMA_MISC_IRQ_EN_MASK);
38     }
39     if (mask & JPEG_EVENT_ERROR) {
40         ptr->CFG &= ~(JPEG_CFG_CODEC_RESTART_ERR_IRQ_EN_MASK);
41     }
42 }
43 
jpeg_enable_irq(JPEG_Type * ptr,uint32_t mask)44 void jpeg_enable_irq(JPEG_Type *ptr, uint32_t mask)
45 {
46     if (mask & JPEG_EVENT_IN_DMA_FINISH) {
47         ptr->INDMA_MISC |= JPEG_INDMA_MISC_IN_DMA_DONE_IRQ_EN_MASK
48             | JPEG_INDMA_MISC_IRQ_EN_MASK;
49     }
50     if (mask & JPEG_EVENT_OUT_DMA_FINISH) {
51         ptr->OUTDMA_MISC |= JPEG_OUTDMA_MISC_OUT_DMA_DONE_IRQ_EN_MASK
52             | JPEG_OUTDMA_MISC_IRQ_EN_MASK;
53     }
54     if (mask & JPEG_EVENT_ERROR) {
55         ptr->CFG |= JPEG_CFG_CODEC_RESTART_ERR_IRQ_EN_MASK;
56     }
57 }
58 
jpeg_reset(JPEG_Type * ptr)59 void jpeg_reset(JPEG_Type *ptr)
60 {
61     jpeg_stop(ptr);
62     jpeg_software_reset(ptr);
63     ptr->STAT = 0xFFFFFFFFUL;
64 
65 }
66 
jpeg_init(JPEG_Type * ptr)67 void jpeg_init(JPEG_Type *ptr)
68 {
69     jpeg_reset(ptr);
70     jpeg_clear_cfg(ptr);
71 }
72 
jpeg_need_csc(jpeg_pixel_format_t in,jpeg_pixel_format_t out)73 static bool jpeg_need_csc(jpeg_pixel_format_t in, jpeg_pixel_format_t out)
74 {
75     return (jpeg_supported_pixel_format[in].is_rgb != jpeg_supported_pixel_format[out].is_rgb);
76 }
77 
jpeg_is_valid_size(uint8_t format,uint32_t width,uint32_t height)78 static bool jpeg_is_valid_size(uint8_t format, uint32_t width, uint32_t height)
79 {
80     uint32_t align;
81     if (format > ARRAY_SIZE(jpeg_supported_sampling)) {
82         return false;
83     }
84     align = jpeg_supported_sampling[format].hy * 8;
85     if (width % align) {
86         return false;
87     }
88     align = jpeg_supported_sampling[format].vy * 8;
89     if (height % align) {
90         return false;
91     }
92     return true;
93 }
94 
95 #define JPEG_HY(x) ((x)->hy)
96 #define JPEG_VY(x) ((x)->vy)
97 #define JPEG_HC(x) ((x)->hc)
98 #define JPEG_VC(x) ((x)->vc)
99 
jpeg_calculate_macro_block_count(uint32_t width,uint32_t height,jpeg_sampling_t * sampling)100 static uint32_t jpeg_calculate_macro_block_count(uint32_t width, uint32_t height, jpeg_sampling_t *sampling)
101 {
102     return (width / (JPEG_HY(sampling) << 3)) * (height / (JPEG_VY(sampling) << 3));
103 }
104 
jpeg_config_interal_regs(JPEG_Type * ptr,bool decoding,uint32_t macro_block_count,uint8_t format)105 static void jpeg_config_interal_regs(JPEG_Type *ptr,
106                                 bool decoding,
107                                 uint32_t macro_block_count,
108                                 uint8_t format)
109 {
110     (void) decoding;
111     uint8_t hy, vy, hc, vc;
112     hy = JPEG_HY(&jpeg_supported_sampling[format]);
113     vy = JPEG_VY(&jpeg_supported_sampling[format]);
114     hc = JPEG_HC(&jpeg_supported_sampling[format]);
115     vc = JPEG_VC(&jpeg_supported_sampling[format]);
116 
117     if (format != JPEG_SUPPORTED_FORMAT_400) {
118         ptr->IMGREG1 =  JPEG_IMGREG1_NCOL_SET(2);
119     } else {
120         ptr->IMGREG1 = 8;
121     }
122     ptr->IMGREG2 = JPEG_IMGREG2_NMCU_SET(macro_block_count - 1);
123     ptr->IMGREG3 = 0;
124     ptr->IMGREG[0] = JPEG_IMGREG_NBLOCK_SET(hy * vy - 1);
125     if (format == JPEG_SUPPORTED_FORMAT_400) {
126         ptr->IMGREG[1] = 0;
127         ptr->IMGREG[2] = 0;
128     } else {
129         ptr->IMGREG[1] = JPEG_IMGREG_NBLOCK_SET(hc * vc - 1)
130             | JPEG_IMGREG_QT_SET(1)
131             | JPEG_IMGREG_HA_SET(1)
132             | JPEG_IMGREG_HD_SET(1);
133         ptr->IMGREG[2] = JPEG_IMGREG_NBLOCK_SET(hc * vc - 1)
134             | JPEG_IMGREG_QT_SET(1)
135             | JPEG_IMGREG_HA_SET(1)
136             | JPEG_IMGREG_HD_SET(1);
137     }
138     ptr->IMGREG[3] = 0;
139 }
140 
jpeg_start_encode(JPEG_Type * ptr,jpeg_job_config_t * config)141 hpm_stat_t jpeg_start_encode(JPEG_Type *ptr, jpeg_job_config_t *config)
142 {
143     uint32_t macro_block_count;
144     uint32_t macro_block_bytes;
145     uint32_t total_bytes;
146     jpeg_sampling_t *sampling;
147 
148     if (!jpeg_is_valid_size(config->jpeg_format, config->width_in_pixel, config->height_in_pixel)) {
149         return status_invalid_argument;
150     }
151 
152     jpeg_disable(ptr);
153     jpeg_software_reset(ptr);
154 
155     sampling = (jpeg_sampling_t *)&jpeg_supported_sampling[config->jpeg_format];
156     macro_block_count = jpeg_calculate_macro_block_count(config->width_in_pixel, config->height_in_pixel, sampling);
157     macro_block_bytes = (JPEG_HY(sampling) * JPEG_VY(sampling)
158             + 2 * JPEG_HC(sampling) * JPEG_VC(sampling)) << 6;
159     total_bytes = macro_block_count * macro_block_bytes;
160 
161     /* input DMA setting */
162     ptr->INDMA_MISC = JPEG_INDMA_MISC_IN_DMA_ID_SET(0)
163         | JPEG_INDMA_MISC_MAX_OT_SET(HPM_JPEG_DEFAULT_MAX_OT)
164         | JPEG_INDMA_MISC_INDMA2D_MASK
165         | JPEG_INDMA_MISC_IN_DMA_REQ_MASK
166         | JPEG_INDMA_MISC_PACK_DIR_SET(config->in_byte_order);
167     ptr->INDMABASE = JPEG_INDMABASE_ADDR_SET(config->in_buffer);
168     ptr->INDMA_CTRL0 = JPEG_INDMA_CTRL0_TTLEN_SET(total_bytes)
169         | JPEG_INDMA_CTRL0_PITCH_SET(config->width_in_pixel * jpeg_supported_pixel_format[config->in_pixel_format].pixel_width);
170     ptr->INDMA_CTRL1 = JPEG_INDMA_CTRL1_ROWLEN_SET(total_bytes >> 16);
171 
172     ptr->INXT_CMD = JPEG_INXT_CMD_ADDR_SET(5) | JPEG_INXT_CMD_OP_VALID_MASK;
173 
174     /* output DMA setting */
175     ptr->OUTDMA_MISC = JPEG_OUTDMA_MISC_EN_OUTCNT_MASK
176         | JPEG_OUTDMA_MISC_INI_OUTCNT_MASK
177         | JPEG_OUTDMA_MISC_OUT_DMA_ID_SET(1)
178         | JPEG_OUTDMA_MISC_OUT_DMA_REQ_MASK
179         | JPEG_OUTDMA_MISC_ADD_ODMA_ENDINGS_MASK
180         | JPEG_OUTDMA_MISC_PACK_DIR_SET(config->out_byte_order);
181     ptr->OUTDMABASE = JPEG_OUTDMABASE_ADDR_SET(config->out_buffer);
182     ptr->OUTDMA_CTRL0 = JPEG_OUTDMA_CTRL0_TTLEN_SET(total_bytes);
183     ptr->OUTDMA_CTRL1 = JPEG_OUTDMA_CTRL1_ROWLEN_SET(total_bytes >> 16);
184 
185     ptr->ONXT_CMD = JPEG_ONXT_CMD_ADDR_SET(5) | JPEG_ONXT_CMD_OP_VALID_MASK;
186 
187     jpeg_config_interal_regs(ptr, false, macro_block_count, config->jpeg_format);
188 
189     ptr->WIDTH = config->width_in_pixel - 1;
190     ptr->HEIGHT = config->height_in_pixel - 1;
191 
192     if (jpeg_need_csc(config->in_pixel_format, config->out_pixel_format)) {
193         if (config->enable_ycbcr) {
194             ptr->RGB2YUV_COEF0 = JPEG_RGB2YUV_COEF0_C0_SET(0x42)
195                 | JPEG_RGB2YUV_COEF0_UV_OFFSET_SET(0x80)
196                 | JPEG_RGB2YUV_COEF0_Y_OFFSET_SET(0x10)
197                 | JPEG_RGB2YUV_COEF0_ENABLE_MASK
198                 | JPEG_RGB2YUV_COEF0_YCBCR_MODE_MASK;
199             ptr->RGB2YUV_COEF1 = JPEG_RGB2YUV_COEF1_C1_SET(0x81)
200                 | JPEG_RGB2YUV_COEF1_C4_SET(0x7B5);
201             ptr->RGB2YUV_COEF2 = JPEG_RGB2YUV_COEF2_C2_SET(0x19)
202                 | JPEG_RGB2YUV_COEF2_C3_SET(0x7DA);
203             ptr->RGB2YUV_COEF3 = JPEG_RGB2YUV_COEF3_C6_SET(0x70)
204                 | JPEG_RGB2YUV_COEF3_C5_SET(0x70);
205             ptr->RGB2YUV_COEF4 = JPEG_RGB2YUV_COEF4_C8_SET(0x7EE)
206                 | JPEG_RGB2YUV_COEF4_C7_SET(0x7A2);
207         } else {
208             ptr->RGB2YUV_COEF0 = JPEG_RGB2YUV_COEF0_C0_SET(0x4D)
209                 | JPEG_RGB2YUV_COEF0_UV_OFFSET_SET(0)
210                 | JPEG_RGB2YUV_COEF0_Y_OFFSET_SET(0x0)
211                 | JPEG_RGB2YUV_COEF0_ENABLE_MASK;
212             ptr->RGB2YUV_COEF1 = JPEG_RGB2YUV_COEF1_C1_SET(0x96)
213                 | JPEG_RGB2YUV_COEF1_C4_SET(0x7B6);
214             ptr->RGB2YUV_COEF2 = JPEG_RGB2YUV_COEF2_C2_SET(0x1D)
215                 | JPEG_RGB2YUV_COEF2_C3_SET(0x7DA);
216             ptr->RGB2YUV_COEF3 = JPEG_RGB2YUV_COEF3_C6_SET(0x9D)
217                 | JPEG_RGB2YUV_COEF3_C5_SET(0x70);
218             ptr->RGB2YUV_COEF4 = JPEG_RGB2YUV_COEF4_C8_SET(0x7E6)
219                 | JPEG_RGB2YUV_COEF4_C7_SET(0x77C);
220         }
221     } else {
222         ptr->RGB2YUV_COEF0 = 0x04030000;
223     }
224 
225     ptr->CFG = JPEG_CFG_CFG_IPATH_SEL_SET(jpeg_supported_pixel_format[config->in_pixel_format].ipath)
226         |  JPEG_CFG_CFG_OPATH_SEL_SET(jpeg_supported_pixel_format[config->out_pixel_format].opath)
227         | JPEG_CFG_CLKGATE_MASK
228         | JPEG_CFG_JDATA_FORMAT_SET(config->jpeg_format)
229         | JPEG_CFG_JPEG_EN_MASK
230         | JPEG_CFG_START_MASK;
231 
232     return status_success;
233 }
234 
235 
jpeg_start_decode(JPEG_Type * ptr,jpeg_job_config_t * config,uint32_t length)236 hpm_stat_t jpeg_start_decode(JPEG_Type *ptr,
237                              jpeg_job_config_t *config,
238                              uint32_t length)
239 {
240     uint32_t macro_block_count;
241     uint32_t macro_block_bytes;
242     uint32_t total_bytes;
243     jpeg_sampling_t *sampling;
244 
245     if (!jpeg_is_valid_size(config->jpeg_format, config->width_in_pixel, config->height_in_pixel)) {
246         return status_invalid_argument;
247     }
248 
249     jpeg_disable(ptr);
250     jpeg_software_reset(ptr);
251 
252     sampling = (jpeg_sampling_t *)&jpeg_supported_sampling[config->jpeg_format];
253     macro_block_count = jpeg_calculate_macro_block_count(config->width_in_pixel, config->height_in_pixel, sampling);
254     macro_block_bytes = (JPEG_HY(sampling) * JPEG_VY(sampling)
255             + 2 * JPEG_HC(sampling) * JPEG_VC(sampling)) << 6;
256     total_bytes = macro_block_count * macro_block_bytes;
257 
258     /* input DMA setting */
259     ptr->INDMA_MISC = JPEG_INDMA_MISC_IN_DMA_ID_SET(1)
260         | JPEG_INDMA_MISC_IN_DMA_REQ_MASK
261         | JPEG_INDMA_MISC_MAX_OT_SET(2)
262         | JPEG_INDMA_MISC_PACK_DIR_SET(config->in_byte_order);
263     ptr->INDMABASE = JPEG_INDMABASE_ADDR_SET(config->in_buffer);
264     /* TODO: check if it has to use the compressed length */
265     ptr->INDMA_CTRL0 = JPEG_INDMA_CTRL0_TTLEN_SET(length);
266     ptr->INDMA_CTRL1 = JPEG_INDMA_CTRL1_ROWLEN_SET(length >> 16);
267     ptr->INXT_CMD = JPEG_INXT_CMD_ADDR_SET(5) | JPEG_INXT_CMD_OP_VALID_MASK;
268 
269     /* output DMA setting */
270     ptr->OUTDMA_MISC = JPEG_OUTDMA_MISC_EN_OUTCNT_MASK
271         | JPEG_OUTDMA_MISC_OUT_DMA_ID_SET(0)
272         | JPEG_OUTDMA_MISC_INI_OUTCNT_MASK
273         | JPEG_OUTDMA_MISC_OUT_DMA_REQ_MASK
274         | JPEG_OUTDMA_MISC_OUTDMA2D_MASK
275         | JPEG_OUTDMA_MISC_PACK_DIR_SET(config->out_byte_order);
276     ptr->OUTDMABASE = JPEG_OUTDMABASE_ADDR_SET(config->out_buffer);
277     ptr->OUTDMA_CTRL0 = JPEG_OUTDMA_CTRL0_TTLEN_SET(total_bytes)
278         | JPEG_OUTDMA_CTRL0_PITCH_SET(config->width_in_pixel * jpeg_supported_pixel_format[config->out_pixel_format].pixel_width);
279     ptr->OUTDMA_CTRL1 = JPEG_OUTDMA_CTRL1_ROWLEN_SET(total_bytes >> 16);
280     ptr->ONXT_CMD = JPEG_ONXT_CMD_ADDR_SET(5) | JPEG_ONXT_CMD_OP_VALID_MASK;
281 
282     jpeg_config_interal_regs(ptr, true, macro_block_count, config->jpeg_format);
283 
284     ptr->WIDTH = config->width_in_pixel - 1;
285     ptr->HEIGHT = config->height_in_pixel - 1;
286 
287     ptr->CSC_COEF0 = 0x4ab01f0
288         | JPEG_CSC_COEF0_YCBCR_MODE_SET(config->enable_ycbcr)
289         | JPEG_CSC_COEF0_ENABLE_SET(jpeg_need_csc(config->in_pixel_format, config->out_pixel_format));
290     ptr->CSC_COEF1 = 0x01980204;
291     ptr->CSC_COEF2 = 0x0730079C;
292 
293     ptr->CFG = JPEG_CFG_CFG_OPATH_SEL_SET(jpeg_supported_pixel_format[config->out_pixel_format].opath)
294         | JPEG_CFG_JDATA_FORMAT_SET(config->jpeg_format)
295         | JPEG_CFG_JPEG_EN_MASK
296         | JPEG_CFG_START_MASK
297         | JPEG_CFG_CLKGATE_MASK
298         | JPEG_CFG_MODE_MASK;
299     return status_success;
300 }
301 
302 #define JPEG_TABLE_WIDTH(x)  (((x) & 0xF00000UL) >> 20)
303 #define JPEG_TABLE_LENGTH(x) (((x) & 0xFFFF0UL) >> 4)
304 #define JPEG_TABLE_TYPE(x)   (((x) & 0xFUL))
305 #define JPEG_TABLE_VALUE_MASK(x) (((x) == 4) ? (0xFFFFFFFFUL) : (uint32_t) ((1 << ((x) << 3)) - 1))
306 
jpeg_fill_table(JPEG_Type * ptr,jpeg_table_t table,uint8_t * data,uint32_t count)307 hpm_stat_t jpeg_fill_table(JPEG_Type *ptr, jpeg_table_t table, uint8_t *data, uint32_t count)
308 {
309     uint32_t i = 0;
310     uint32_t width = JPEG_TABLE_WIDTH(table);
311     uint32_t length = JPEG_TABLE_LENGTH(table);
312     uint32_t type = JPEG_TABLE_TYPE(table);
313     uint32_t *p;
314 
315     if (length != count) {
316         return status_invalid_argument;
317     }
318 
319     ptr->BUFADDR = type << 28;
320     for (i = 0; i < count; i++) {
321         p = (uint32_t *) &data[i * width];
322         ptr->BUFDATA = JPEG_BUFADDR_ADDR_SET(*p & JPEG_TABLE_VALUE_MASK(width));
323     }
324     return status_success;
325 }
326 
327