]> rtime.felk.cvut.cz Git - hercules2020/nv-tegra/linux-4.4.git/blob - drivers/media/platform/tegra/camera/sensor_common.c
media: tegra: camera: fix embedded data error
[hercules2020/nv-tegra/linux-4.4.git] / drivers / media / platform / tegra / camera / sensor_common.c
1 /*
2  * sensor_common.c - utilities for tegra sensor drivers
3  *
4  * Copyright (c) 2017, NVIDIA CORPORATION.  All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include <media/sensor_common.h>
20 #include <linux/of_graph.h>
21 #include <linux/string.h>
22
23 static int read_property_u32(
24         struct device_node *node, const char *name, u32 *value)
25 {
26         const char *str;
27         int err = 0;
28
29         err = of_property_read_string(node, name, &str);
30         if (err)
31                 return -ENODATA;
32
33         err = kstrtou32(str, 10, value);
34         if (err)
35                 return -EFAULT;
36
37         return 0;
38 }
39
40 static int read_property_u64(
41         struct device_node *node, const char *name, u64 *value)
42 {
43         const char *str;
44         int err = 0;
45
46         err = of_property_read_string(node, name, &str);
47         if (err)
48                 return -ENODATA;
49
50         err = kstrtou64(str, 10, value);
51         if (err)
52                 return -EFAULT;
53
54         return 0;
55 }
56
57 static int sensor_common_parse_signal_props(
58         struct device *dev, struct device_node *node,
59         struct sensor_signal_properties *signal)
60 {
61         const char *temp_str;
62         int err = 0;
63
64         /* Do not report error for these properties yet */
65         read_property_u32(node, "readout_orientation",
66                 &signal->readout_orientation);
67         read_property_u32(node, "num_lanes",
68                 &signal->num_lanes);
69         read_property_u32(node, "mclk_khz",
70                 &signal->mclk_freq);
71         read_property_u64(node, "pix_clk_hz",
72                 &signal->pixel_clock.val);
73         read_property_u32(node, "cil_settletime",
74                 &signal->cil_settletime);
75         /* initialize default if this prop not available */
76         err = of_property_read_string(node, "discontinuous_clk",
77                 &temp_str);
78         if (!err)
79                 signal->discontinuous_clk =
80                         !strncmp(temp_str, "yes", sizeof("yes"));
81         else
82                 signal->discontinuous_clk = 1;
83         /* initialize default if this prop not available */
84         err = of_property_read_string(node, "dpcm_enable",
85                 &temp_str);
86         if (!err)
87                 signal->dpcm_enable =
88                         !strncmp(temp_str, "true", sizeof("true"));
89         else
90                 signal->dpcm_enable = 0;
91
92         return 0;
93 }
94
95 static int extract_pixel_format(
96         const char *pixel_t, u32 *format)
97 {
98         size_t size = strnlen(pixel_t, OF_MAX_STR_LEN);
99
100         if (strncmp(pixel_t, "bayer_bggr10", size) == 0)
101                 *format = V4L2_PIX_FMT_SBGGR10;
102         else if (strncmp(pixel_t, "bayer_rggb10", size) == 0)
103                 *format = V4L2_PIX_FMT_SRGGB10;
104         else if (strncmp(pixel_t, "bayer_bggr12", size) == 0)
105                 *format = V4L2_PIX_FMT_SBGGR12;
106         else if (strncmp(pixel_t, "bayer_rggb12", size) == 0)
107                 *format = V4L2_PIX_FMT_SRGGB12;
108         else if (strncmp(pixel_t, "bayer_wdr_pwl_rggb12", size) == 0)
109                 *format = V4L2_PIX_FMT_SRGGB12;
110         else if (strncmp(pixel_t, "bayer_xbggr10p", size) == 0)
111                 *format = V4L2_PIX_FMT_XBGGR10P;
112         else if (strncmp(pixel_t, "bayer_xrggb10p", size) == 0)
113                 *format = V4L2_PIX_FMT_XRGGB10P;
114         else {
115                 pr_err("%s: Need to extend format%s\n", __func__, pixel_t);
116                 return -EINVAL;
117         }
118
119         return 0;
120 }
121
122 static int sensor_common_parse_image_props(
123         struct device *dev, struct device_node *node,
124         struct sensor_image_properties *image)
125 {
126         const char *temp_str;
127         int err = 0;
128         const char *phase_str, *mode_str;
129         int depth;
130         char pix_format[24];
131
132         err = read_property_u32(node, "active_w",
133                 &image->width);
134         if (err) {
135                 dev_err(dev, "%s:active_w property missing\n", __func__);
136                 goto fail;
137         }
138
139         err = read_property_u32(node, "active_h",
140                 &image->height);
141         if (err) {
142                 dev_err(dev, "%s:active_h property missing\n", __func__);
143                 goto fail;
144         }
145
146         err = read_property_u32(node, "line_length",
147                 &image->line_length);
148         if (err) {
149                 dev_err(dev, "%s:Line length property missing\n", __func__);
150                 goto fail;
151         }
152
153         /* embedded_metadata_height is optional */
154         read_property_u32(node, "embedded_metadata_height",
155                 &image->embedded_metadata_height);
156
157         err = of_property_read_string(node, "pixel_t", &temp_str);
158         if (err) {
159                 dev_err(dev, "%s:pixel_t property missing\n", __func__);
160
161                 /* check for alternative format string */
162                 err = of_property_read_string(node, "pixel_phase", &phase_str);
163                 if (err) {
164                         dev_err(dev,
165                                 "%s:pixel_phase property missing\n",
166                                 __func__);
167                         goto fail;
168                 }
169                 err = of_property_read_string(node, "mode_type", &mode_str);
170                 if (err) {
171                         dev_err(dev,
172                                 "%s:mode_type property missing\n",
173                                 __func__);
174                         goto fail;
175                 }
176                 err = read_property_u32(node, "csi_pixel_bit_depth", &depth);
177                 if (err) {
178                         dev_err(dev,
179                                 "%s:csi_pixel_bit_depth property missing\n",
180                                 __func__);
181                         goto fail;
182                 }
183                 sprintf(pix_format, "%s_%s%d", mode_str, phase_str, depth);
184                 temp_str = pix_format;
185         }
186         err = extract_pixel_format(temp_str, &image->pixel_format);
187         if (err) {
188                 dev_err(dev, "Unsupported pixel format\n");
189                 goto fail;
190         }
191
192 fail:
193         return err;
194 }
195
196 static int sensor_common_parse_dv_timings(
197         struct device *dev, struct device_node *node,
198         struct sensor_dv_timings *timings)
199 {
200         /* Do not report error for these properties yet */
201         read_property_u32(node, "horz_front_porch",
202                 &timings->hfrontporch);
203         read_property_u32(node, "horz_sync",
204                 &timings->hsync);
205         read_property_u32(node, "horz_back_porch",
206                 &timings->hbackporch);
207         read_property_u32(node, "vert_front_porch",
208                 &timings->vfrontporch);
209         read_property_u32(node, "vert_sync",
210                 &timings->vsync);
211         read_property_u32(node, "vert_back_porch",
212                 &timings->vbackporch);
213
214         return 0;
215 }
216
217 static int sensor_common_parse_control_props(
218         struct device *dev, struct device_node *node,
219         struct sensor_control_properties *control)
220 {
221         int err = 0;
222
223         err = read_property_u32(node, "gain_factor",
224                 &control->gain_factor);
225         if (err) {
226                 dev_dbg(dev, "%s:%s:property missing\n",
227                         __func__, "gain_factor");
228                 return 0;
229         }
230
231         err = read_property_u32(node, "framerate_factor",
232                 &control->framerate_factor);
233         if (err)
234                 dev_err(dev, "%s:%s:property missing\n",
235                         __func__, "framerate_factor");
236
237         /* ignore err for this prop */
238         err = read_property_u32(node, "inherent_gain",
239                 &control->inherent_gain);
240
241         err = read_property_u32(node, "min_gain_val",
242                 &control->min_gain_val);
243         if (err)
244                 dev_err(dev, "%s:%s:property missing\n",
245                         __func__, "min_gain_val");
246
247         err = read_property_u32(node, "max_gain_val",
248                 &control->max_gain_val);
249         if (err)
250                 dev_err(dev, "%s:%s:property missing\n",
251                         __func__, "max_gain_val");
252
253         /* ignore err for this prop */
254         err = read_property_u32(node, "min_hdr_ratio",
255                 &control->min_hdr_ratio);
256         err = read_property_u32(node, "max_hdr_ratio",
257                 &control->max_hdr_ratio);
258
259         err = read_property_u32(node, "min_framerate",
260                 &control->min_framerate);
261         if (err)
262                 dev_err(dev, "%s:%s:property missing\n",
263                         __func__, "min_framerate");
264
265         err = read_property_u32(node, "max_framerate",
266                 &control->max_framerate);
267         if (err)
268                 dev_err(dev, "%s:%s:property missing\n",
269                         __func__, "max_framerate");
270
271         err = read_property_u64(node, "min_exp_time",
272                 &control->min_exp_time.val);
273         if (err)
274                 dev_err(dev, "%s:%s:property missing\n",
275                         __func__, "min_exp_time");
276
277         err = read_property_u64(node, "max_exp_time",
278                 &control->max_exp_time.val);
279         if (err)
280                 dev_err(dev, "%s:%s:property missing\n",
281                         __func__, "max_exp_time");
282
283         return err;
284 }
285
286 int sensor_common_init_sensor_properties(
287         struct device *dev, struct device_node *np,
288         struct sensor_properties *sensor)
289 {
290         char temp_str[OF_MAX_STR_LEN];
291         struct device_node *node = NULL;
292         int num_modes = 0;
293         int err, i;
294
295         /* get number of modes */
296         for (i = 0; num_modes < MAX_NUM_SENSOR_MODES; i++) {
297                 snprintf(temp_str, sizeof(temp_str), "%s%d",
298                         OF_SENSORMODE_PREFIX, i);
299                 of_node_get(np);
300                 node = of_get_child_by_name(np, temp_str);
301                 of_node_put(node);
302                 if (node == NULL)
303                         break;
304                 num_modes++;
305         }
306         sensor->num_modes = num_modes;
307
308         if (!num_modes) {
309                 err = 0;
310                 goto fail;
311         }
312
313         sensor->sensor_modes = devm_kzalloc(dev,
314                 num_modes * sizeof(struct sensor_mode_properties),
315                 GFP_KERNEL);
316         if (!sensor->sensor_modes) {
317                 dev_err(dev, "Failed to allocate memory for sensor modes\n");
318                 err = -ENOMEM;
319                 goto fail;
320         }
321         memset(sensor->sensor_modes, 0, num_modes *
322                sizeof(struct sensor_mode_properties));
323
324         for (i = 0; i < num_modes; i++) {
325                 snprintf(temp_str, sizeof(temp_str), "%s%d",
326                         OF_SENSORMODE_PREFIX, i);
327                 of_node_get(np);
328                 node = of_get_child_by_name(np, temp_str);
329                 if (node == NULL) {
330                         dev_err(dev, "Failed to find mode\n");
331                         err = -ENODATA;
332                         goto fail;
333                 };
334
335                 err = sensor_common_parse_signal_props(dev, node,
336                         &sensor->sensor_modes[i].signal_properties);
337                 if (err) {
338                         dev_err(dev, "Failed to read signal properties\n");
339                         goto fail;
340                 }
341
342                 err = sensor_common_parse_image_props(dev, node,
343                         &sensor->sensor_modes[i].image_properties);
344                 if (err) {
345                         dev_err(dev, "Failed to read image properties\n");
346                         goto fail;
347                 }
348
349                 err = sensor_common_parse_dv_timings(dev, node,
350                         &sensor->sensor_modes[i].dv_timings);
351                 if (err) {
352                         dev_err(dev, "Failed to read DV timings\n");
353                         goto fail;
354                 }
355
356                 err = sensor_common_parse_control_props(dev, node,
357                         &sensor->sensor_modes[i].control_properties);
358                 if (err) {
359                         dev_err(dev, "Failed to read control properties\n");
360                         goto fail;
361                 }
362                 of_node_put(node);
363         }
364
365         return 0;
366
367 fail:
368         of_node_put(node);
369         return err;
370 }
371 EXPORT_SYMBOL(sensor_common_init_sensor_properties);