WIP FPC-III support
[linux/fpc-iii.git] / drivers / media / platform / sti / delta / delta-mjpeg-hdr.c
blob90e5b2f72c82b60205bed2703f1e11d00120148f
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) STMicroelectronics SA 2013
4 * Author: Hugues Fruchet <hugues.fruchet@st.com> for STMicroelectronics.
5 */
7 #include "delta.h"
8 #include "delta-mjpeg.h"
10 #define MJPEG_SOF_0 0xc0
11 #define MJPEG_SOF_1 0xc1
12 #define MJPEG_SOI 0xd8
13 #define MJPEG_MARKER 0xff
15 static char *header_str(struct mjpeg_header *header,
16 char *str,
17 unsigned int len)
19 char *cur = str;
20 unsigned int left = len;
22 if (!header)
23 return "";
25 snprintf(cur, left, "[MJPEG header]\n"
26 "|- length = %d\n"
27 "|- precision = %d\n"
28 "|- width = %d\n"
29 "|- height = %d\n"
30 "|- components = %d\n",
31 header->length,
32 header->sample_precision,
33 header->frame_width,
34 header->frame_height,
35 header->nb_of_components);
37 return str;
40 static int delta_mjpeg_read_sof(struct delta_ctx *pctx,
41 unsigned char *data, unsigned int size,
42 struct mjpeg_header *header)
44 struct delta_dev *delta = pctx->dev;
45 unsigned int offset = 0;
47 if (size < 64)
48 goto err_no_more;
50 memset(header, 0, sizeof(*header));
51 header->length = be16_to_cpu(*(__be16 *)(data + offset));
52 offset += sizeof(u16);
53 header->sample_precision = *(u8 *)(data + offset);
54 offset += sizeof(u8);
55 header->frame_height = be16_to_cpu(*(__be16 *)(data + offset));
56 offset += sizeof(u16);
57 header->frame_width = be16_to_cpu(*(__be16 *)(data + offset));
58 offset += sizeof(u16);
59 header->nb_of_components = *(u8 *)(data + offset);
60 offset += sizeof(u8);
62 if (header->nb_of_components >= MJPEG_MAX_COMPONENTS) {
63 dev_err(delta->dev,
64 "%s unsupported number of components (%d > %d)\n",
65 pctx->name, header->nb_of_components,
66 MJPEG_MAX_COMPONENTS);
67 return -EINVAL;
70 if ((offset + header->nb_of_components *
71 sizeof(header->components[0])) > size)
72 goto err_no_more;
74 return 0;
76 err_no_more:
77 dev_err(delta->dev,
78 "%s sof: reached end of %d size input stream\n",
79 pctx->name, size);
80 return -ENODATA;
83 int delta_mjpeg_read_header(struct delta_ctx *pctx,
84 unsigned char *data, unsigned int size,
85 struct mjpeg_header *header,
86 unsigned int *data_offset)
88 struct delta_dev *delta = pctx->dev;
89 unsigned char str[200];
91 unsigned int ret = 0;
92 unsigned int offset = 0;
93 unsigned int soi = 0;
95 if (size < 2)
96 goto err_no_more;
98 offset = 0;
99 while (1) {
100 if (data[offset] == MJPEG_MARKER)
101 switch (data[offset + 1]) {
102 case MJPEG_SOI:
103 soi = 1;
104 *data_offset = offset;
105 break;
107 case MJPEG_SOF_0:
108 case MJPEG_SOF_1:
109 if (!soi) {
110 dev_err(delta->dev,
111 "%s wrong sequence, got SOF while SOI not seen\n",
112 pctx->name);
113 return -EINVAL;
116 ret = delta_mjpeg_read_sof(pctx,
117 &data[offset + 2],
118 size - (offset + 2),
119 header);
120 if (ret)
121 goto err;
123 goto done;
125 default:
126 break;
129 offset++;
130 if ((offset + 2) >= size)
131 goto err_no_more;
134 done:
135 dev_dbg(delta->dev,
136 "%s found header @ offset %d:\n%s", pctx->name,
137 *data_offset,
138 header_str(header, str, sizeof(str)));
139 return 0;
141 err_no_more:
142 dev_err(delta->dev,
143 "%s no header found within %d bytes input stream\n",
144 pctx->name, size);
145 return -ENODATA;
147 err:
148 return ret;