blob: 444e218e15ab224d978e7879da2c1b23f3260933 [file] [log] [blame]
Laurent Pinchart3265eda2015-12-15 03:18:06 +02001/*
2 * Greybus Camera protocol driver.
3 *
4 * Copyright 2015 Google Inc.
5 * Copyright 2015 Linaro Ltd.
6 *
7 * Released under the GPLv2 only.
8 */
9
10#include <linux/debugfs.h>
11#include <linux/fs.h>
12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <linux/slab.h>
15#include <linux/string.h>
16#include <linux/uaccess.h>
17#include <linux/vmalloc.h>
18
Gjorgji Rosikopulos3a8dba42016-01-13 21:52:38 +020019#include "gb-camera.h"
Laurent Pinchart3265eda2015-12-15 03:18:06 +020020#include "greybus.h"
21#include "greybus_protocols.h"
22
23enum gb_camera_debugs_buffer_id {
24 GB_CAMERA_DEBUGFS_BUFFER_CAPABILITIES,
25 GB_CAMERA_DEBUGFS_BUFFER_STREAMS,
26 GB_CAMERA_DEBUGFS_BUFFER_CAPTURE,
27 GB_CAMERA_DEBUGFS_BUFFER_FLUSH,
28 GB_CAMERA_DEBUGFS_BUFFER_MAX,
29};
30
31struct gb_camera_debugfs_buffer {
32 char data[PAGE_SIZE];
33 size_t length;
34};
35
36/**
37 * struct gb_camera - A Greybus Camera Device
38 * @connection: the greybus connection for camera control
39 * @data_connected: whether the data connection has been established
40 * @debugfs: debugfs entries for camera protocol operations testing
41 */
42struct gb_camera {
43 struct gb_connection *connection;
44 bool data_connected;
45
46 struct {
47 struct dentry *root;
48 struct gb_camera_debugfs_buffer *buffers;
49 } debugfs;
50};
51
52struct gb_camera_stream_config {
53 unsigned int width;
54 unsigned int height;
55 unsigned int format;
56 unsigned int vc;
57 unsigned int dt[2];
58 unsigned int max_size;
59};
60
Gjorgji Rosikopulos3a8dba42016-01-13 21:52:38 +020061struct gb_camera_fmt_map {
62 enum v4l2_mbus_pixelcode mbus_code;
63 unsigned int gb_format;
64};
65
66/* GB format to media code map */
67static const struct gb_camera_fmt_map mbus_to_gbus_format[] = {
68 {
69 .mbus_code = V4L2_MBUS_FMT_UYVY8_1X16,
70 .gb_format = 0x01,
71 },
72 {
Gjorgji Rosikopulos7c154712016-01-22 17:59:44 +020073 .mbus_code = V4L2_MBUS_FMT_NV12_1x8,
74 .gb_format = 0x12,
75 },
76 {
77 .mbus_code = V4L2_MBUS_FMT_NV21_1x8,
78 .gb_format = 0x13,
79 },
80 {
81 .mbus_code = V4L2_MBUS_FMT_YU12_1x8,
Gjorgji Rosikopulos3a8dba42016-01-13 21:52:38 +020082 .gb_format = 0x16,
83 },
84 {
Gjorgji Rosikopulos7c154712016-01-22 17:59:44 +020085 .mbus_code = V4L2_MBUS_FMT_YV12_1x8,
Gjorgji Rosikopulos3a8dba42016-01-13 21:52:38 +020086 .gb_format = 0x17,
87 },
88 {
89 .mbus_code = V4L2_MBUS_FMT_JPEG_1X8,
90 .gb_format = 0x40,
91 }
92};
93
Laurent Pinchart3265eda2015-12-15 03:18:06 +020094#define ES2_APB_CDSI0_CPORT 16
95#define ES2_APB_CDSI1_CPORT 17
96
97#define GB_CAMERA_MAX_SETTINGS_SIZE 8192
98
99#define gcam_dbg(gcam, format...) \
100 dev_dbg(&gcam->connection->bundle->dev, format)
101#define gcam_info(gcam, format...) \
102 dev_info(&gcam->connection->bundle->dev, format)
103#define gcam_err(gcam, format...) \
104 dev_err(&gcam->connection->bundle->dev, format)
105
106/* -----------------------------------------------------------------------------
107 * Camera Protocol Operations
108 */
109
Laurent Pinchartc161c0f2016-02-14 02:33:04 +0200110static int gb_camera_set_intf_power_mode(struct gb_camera *gcam, u8 intf_id,
111 bool hs)
112{
113 struct gb_svc *svc = gcam->connection->hd->svc;
114 int ret;
115
116 if (hs)
117 ret = gb_svc_intf_set_power_mode(svc, intf_id,
118 GB_SVC_UNIPRO_HS_SERIES_A,
119 GB_SVC_UNIPRO_FAST_MODE, 2, 2,
120 GB_SVC_UNIPRO_FAST_MODE, 2, 2,
121 GB_SVC_PWRM_RXTERMINATION |
122 GB_SVC_PWRM_TXTERMINATION, 0);
123 else
124 ret = gb_svc_intf_set_power_mode(svc, intf_id,
125 GB_SVC_UNIPRO_HS_SERIES_A,
126 GB_SVC_UNIPRO_SLOW_AUTO_MODE,
127 1, 2,
128 GB_SVC_UNIPRO_SLOW_AUTO_MODE,
129 1, 2,
130 0, 0);
131
132 return ret;
133}
134
135static int gb_camera_set_power_mode(struct gb_camera *gcam, bool hs)
136{
137 struct gb_interface *intf = gcam->connection->intf;
138 struct gb_svc *svc = gcam->connection->hd->svc;
139 int ret;
140
141 ret = gb_camera_set_intf_power_mode(gcam, intf->interface_id, hs);
142 if (ret < 0) {
143 gcam_err(gcam, "failed to set module interface to %s (%d)\n",
144 hs ? "HS" : "PWM", ret);
145 return ret;
146 }
147
148 ret = gb_camera_set_intf_power_mode(gcam, svc->ap_intf_id, hs);
149 if (ret < 0) {
Laurent Pinchartb573b0e2016-02-14 02:33:05 +0200150 gb_camera_set_intf_power_mode(gcam, intf->interface_id, !hs);
Laurent Pinchartc161c0f2016-02-14 02:33:04 +0200151 gcam_err(gcam, "failed to set AP interface to %s (%d)\n",
152 hs ? "HS" : "PWM", ret);
153 return ret;
154 }
155
156 return 0;
157}
158
Greg Kroah-Hartmaned4596e92015-12-22 18:21:51 -0800159struct ap_csi_config_request {
160 __u8 csi_id;
Jacopo Mondi27e18d82016-02-23 11:22:49 +0100161 __u8 flags;
162#define GB_CAMERA_CSI_FLAG_CLOCK_CONTINUOUS 0x01
Greg Kroah-Hartmaned4596e92015-12-22 18:21:51 -0800163 __u8 num_lanes;
164 __u8 padding;
165 __le32 bus_freq;
Jacopo Mondi446091c2016-02-23 11:22:48 +0100166 __le32 lines_per_second;
Greg Kroah-Hartmaned4596e92015-12-22 18:21:51 -0800167} __packed;
168
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200169static int gb_camera_configure_streams(struct gb_camera *gcam,
Laurent Pinchart40684872016-01-15 01:33:55 +0200170 unsigned int *num_streams,
171 unsigned int *flags,
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200172 struct gb_camera_stream_config *streams)
173{
174 struct gb_camera_configure_streams_request *req;
175 struct gb_camera_configure_streams_response *resp;
Greg Kroah-Hartmaned4596e92015-12-22 18:21:51 -0800176 struct ap_csi_config_request csi_cfg;
Jacopo Mondi4fbf69c2016-01-23 19:44:46 -0800177
Laurent Pinchart40684872016-01-15 01:33:55 +0200178 unsigned int nstreams = *num_streams;
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200179 unsigned int i;
180 size_t req_size;
181 size_t resp_size;
182 int ret;
183
184 if (nstreams > GB_CAMERA_MAX_STREAMS)
185 return -EINVAL;
186
187 req_size = sizeof(*req) + nstreams * sizeof(req->config[0]);
188 resp_size = sizeof(*resp) + nstreams * sizeof(resp->config[0]);
189
190 req = kmalloc(req_size, GFP_KERNEL);
191 resp = kmalloc(resp_size, GFP_KERNEL);
192 if (!req || !resp) {
193 ret = -ENOMEM;
194 goto done;
195 }
196
Jacopo Mondib787d412016-01-08 18:13:20 +0200197 req->num_streams = nstreams;
Laurent Pinchart40684872016-01-15 01:33:55 +0200198 req->flags = *flags;
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200199 req->padding = 0;
200
201 for (i = 0; i < nstreams; ++i) {
202 struct gb_camera_stream_config_request *cfg = &req->config[i];
203
Laurent Pinchartc6622212015-12-18 21:23:21 +0200204 cfg->width = cpu_to_le16(streams[i].width);
205 cfg->height = cpu_to_le16(streams[i].height);
206 cfg->format = cpu_to_le16(streams[i].format);
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200207 cfg->padding = 0;
208 }
209
210 ret = gb_operation_sync(gcam->connection,
211 GB_CAMERA_TYPE_CONFIGURE_STREAMS,
212 req, req_size, resp, resp_size);
213 if (ret < 0)
Laurent Pinchart66c36072016-02-14 02:33:06 +0200214 goto done;
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200215
Jacopo Mondib787d412016-01-08 18:13:20 +0200216 if (resp->num_streams > nstreams) {
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200217 gcam_dbg(gcam, "got #streams %u > request %u\n",
Jacopo Mondib787d412016-01-08 18:13:20 +0200218 resp->num_streams, nstreams);
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200219 ret = -EIO;
Laurent Pinchart66c36072016-02-14 02:33:06 +0200220 goto done;
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200221 }
222
223 if (resp->padding != 0) {
224 gcam_dbg(gcam, "response padding != 0");
225 ret = -EIO;
Laurent Pinchart66c36072016-02-14 02:33:06 +0200226 goto done;
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200227 }
228
229 for (i = 0; i < nstreams; ++i) {
230 struct gb_camera_stream_config_response *cfg = &resp->config[i];
231
Laurent Pinchartc6622212015-12-18 21:23:21 +0200232 streams[i].width = le16_to_cpu(cfg->width);
233 streams[i].height = le16_to_cpu(cfg->height);
234 streams[i].format = le16_to_cpu(cfg->format);
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200235 streams[i].vc = cfg->virtual_channel;
236 streams[i].dt[0] = cfg->data_type[0];
237 streams[i].dt[1] = cfg->data_type[1];
Laurent Pinchartc6622212015-12-18 21:23:21 +0200238 streams[i].max_size = le32_to_cpu(cfg->max_size);
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200239
240 if (cfg->padding[0] || cfg->padding[1] || cfg->padding[2]) {
241 gcam_dbg(gcam, "stream #%u padding != 0", i);
242 ret = -EIO;
Laurent Pinchart66c36072016-02-14 02:33:06 +0200243 goto done;
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200244 }
245 }
246
Laurent Pinchart640924d2016-02-14 02:33:07 +0200247 if ((resp->flags & GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED) ||
248 (*flags & GB_CAMERA_CONFIGURE_STREAMS_TEST_ONLY)) {
Jacopo Mondif121d792016-02-05 09:35:32 +0100249 *flags = resp->flags;
250 *num_streams = resp->num_streams;
Laurent Pinchart66c36072016-02-14 02:33:06 +0200251 goto done;
252 }
253
254 /* Setup unipro link speed. */
Laurent Pinchart640924d2016-02-14 02:33:07 +0200255 ret = gb_camera_set_power_mode(gcam, nstreams != 0);
256 if (ret < 0)
257 goto done;
Greg Kroah-Hartmaned4596e92015-12-22 18:21:51 -0800258
Jacopo Mondi446091c2016-02-23 11:22:48 +0100259 /*
260 * Configure the APB1 CSI transmitter using the lines count reported by
261 * the camera module, but with hard-coded bus frequency and lanes number.
262 *
263 * TODO: use the clocking and size informations reported by camera module
264 * to compute the required CSI bandwidth, and configure the CSI receiver
265 * on AP side, and the CSI transmitter on APB1 side accordingly.
266 */
Laurent Pinchart640924d2016-02-14 02:33:07 +0200267 memset(&csi_cfg, 0, sizeof(csi_cfg));
268
Jacopo Mondif121d792016-02-05 09:35:32 +0100269 if (nstreams) {
Laurent Pinchart142b21f2015-12-18 21:23:25 +0200270 csi_cfg.csi_id = 1;
Jacopo Mondi27e18d82016-02-23 11:22:49 +0100271 csi_cfg.flags = 0;
Laurent Pinchart1f67ee52015-12-31 04:20:56 +0200272 csi_cfg.num_lanes = 4;
Greg Kroah-Hartmaned4596e92015-12-22 18:21:51 -0800273 csi_cfg.bus_freq = cpu_to_le32(960000000);
Jacopo Mondi446091c2016-02-23 11:22:48 +0100274 csi_cfg.lines_per_second = resp->lines_per_second;
Greg Kroah-Hartmaned4596e92015-12-22 18:21:51 -0800275 ret = gb_hd_output(gcam->connection->hd, &csi_cfg,
Greg Kroah-Hartmane5273382015-12-31 11:14:33 -0800276 sizeof(csi_cfg),
277 GB_APB_REQUEST_CSI_TX_CONTROL, false);
Jacopo Mondif121d792016-02-05 09:35:32 +0100278 } else {
Laurent Pinchart142b21f2015-12-18 21:23:25 +0200279 csi_cfg.csi_id = 1;
Greg Kroah-Hartmaned4596e92015-12-22 18:21:51 -0800280 ret = gb_hd_output(gcam->connection->hd, &csi_cfg,
Greg Kroah-Hartmane5273382015-12-31 11:14:33 -0800281 sizeof(csi_cfg),
282 GB_APB_REQUEST_CSI_TX_CONTROL, false);
Laurent Pinchart142b21f2015-12-18 21:23:25 +0200283 }
284
285 if (ret < 0)
286 gcam_err(gcam, "failed to %s the CSI transmitter\n",
287 nstreams ? "start" : "stop");
288
Jacopo Mondif121d792016-02-05 09:35:32 +0100289 *flags = resp->flags;
Laurent Pinchart40684872016-01-15 01:33:55 +0200290 *num_streams = resp->num_streams;
291 ret = 0;
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200292
293done:
294 kfree(req);
295 kfree(resp);
296 return ret;
297}
298
299static int gb_camera_capture(struct gb_camera *gcam, u32 request_id,
300 unsigned int streams, unsigned int num_frames,
301 size_t settings_size, const void *settings)
302{
303 struct gb_camera_capture_request *req;
304 size_t req_size;
Johan Hovoldb9f71bc2015-12-30 11:08:01 +0100305 int ret;
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200306
307 if (settings_size > GB_CAMERA_MAX_SETTINGS_SIZE)
308 return -EINVAL;
309
310 req_size = sizeof(*req) + settings_size;
311 req = kmalloc(req_size, GFP_KERNEL);
312 if (!req)
313 return -ENOMEM;
314
Laurent Pinchartc6622212015-12-18 21:23:21 +0200315 req->request_id = cpu_to_le32(request_id);
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200316 req->streams = streams;
317 req->padding = 0;
Laurent Pinchartc6622212015-12-18 21:23:21 +0200318 req->num_frames = cpu_to_le16(num_frames);
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200319 memcpy(req->settings, settings, settings_size);
320
Johan Hovoldb9f71bc2015-12-30 11:08:01 +0100321 ret = gb_operation_sync(gcam->connection, GB_CAMERA_TYPE_CAPTURE,
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200322 req, req_size, NULL, 0);
Johan Hovoldb9f71bc2015-12-30 11:08:01 +0100323
324 kfree(req);
325
326 return ret;
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200327}
328
329static int gb_camera_flush(struct gb_camera *gcam, u32 *request_id)
330{
331 struct gb_camera_flush_response resp;
332 int ret;
333
334 ret = gb_operation_sync(gcam->connection, GB_CAMERA_TYPE_FLUSH, NULL, 0,
335 &resp, sizeof(resp));
336 if (ret < 0)
337 return ret;
338
339 if (request_id)
Laurent Pinchartc6622212015-12-18 21:23:21 +0200340 *request_id = le32_to_cpu(resp.request_id);
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200341
342 return 0;
343}
344
345static int gb_camera_event_recv(u8 type, struct gb_operation *op)
346{
347 struct gb_camera *gcam = op->connection->private;
348 struct gb_camera_metadata_request *payload;
349 struct gb_message *request;
350
351 if (type != GB_CAMERA_TYPE_METADATA) {
352 gcam_err(gcam, "Unsupported unsolicited event: %u\n", type);
353 return -EINVAL;
354 }
355
356 request = op->request;
357
358 if (request->payload_size < sizeof(*payload)) {
359 gcam_err(gcam, "Wrong event size received (%zu < %zu)\n",
360 request->payload_size, sizeof(*payload));
361 return -EINVAL;
362 }
363
364 payload = request->payload;
365
366 gcam_dbg(gcam, "received metadata for request %u, frame %u, stream %u\n",
367 payload->request_id, payload->frame_number, payload->stream);
368
369 return 0;
370}
371
372/* -----------------------------------------------------------------------------
Gjorgji Rosikopulos3a8dba42016-01-13 21:52:38 +0200373 * Interface with HOST ara camera.
374 */
375static unsigned int gb_camera_mbus_to_gb(enum v4l2_mbus_pixelcode mbus_code)
376{
377 unsigned int i;
378
379 for (i = 0; i < ARRAY_SIZE(mbus_to_gbus_format); i++) {
380 if (mbus_to_gbus_format[i].mbus_code == mbus_code)
381 return mbus_to_gbus_format[i].gb_format;
382 }
383 return mbus_to_gbus_format[0].gb_format;
384}
385
386static enum v4l2_mbus_pixelcode gb_camera_gb_to_mbus(u16 gb_fmt)
387{
388 unsigned int i;
389
390 for (i = 0; i < ARRAY_SIZE(mbus_to_gbus_format); i++) {
391 if (mbus_to_gbus_format[i].gb_format == gb_fmt)
392 return mbus_to_gbus_format[i].mbus_code;
393 }
394 return mbus_to_gbus_format[0].mbus_code;
395}
396
Gjorgji Rosikopulos5b032712016-01-17 19:52:21 +0200397static int gb_camera_op_configure_streams(void *priv, unsigned int *nstreams,
398 unsigned int *flags, struct gb_camera_stream *streams)
Gjorgji Rosikopulos3a8dba42016-01-13 21:52:38 +0200399{
400 struct gb_camera *gcam = priv;
401 struct gb_camera_stream_config *gb_streams;
Gjorgji Rosikopulos5b032712016-01-17 19:52:21 +0200402 unsigned int gb_flags = 0;
403 unsigned int gb_nstreams = *nstreams;
Gjorgji Rosikopulos3a8dba42016-01-13 21:52:38 +0200404 unsigned int i;
405 int ret;
406
Gjorgji Rosikopulos5b032712016-01-17 19:52:21 +0200407 if (gb_nstreams > GB_CAMERA_MAX_STREAMS)
Gjorgji Rosikopulos3a8dba42016-01-13 21:52:38 +0200408 return -EINVAL;
409
Gjorgji Rosikopulos5b032712016-01-17 19:52:21 +0200410 gb_streams = kzalloc(gb_nstreams * sizeof(*gb_streams), GFP_KERNEL);
Gjorgji Rosikopulos3a8dba42016-01-13 21:52:38 +0200411 if (!gb_streams)
412 return -ENOMEM;
413
Gjorgji Rosikopulos5b032712016-01-17 19:52:21 +0200414 for (i = 0; i < gb_nstreams; i++) {
Gjorgji Rosikopulos3a8dba42016-01-13 21:52:38 +0200415 gb_streams[i].width = streams[i].width;
416 gb_streams[i].height = streams[i].height;
417 gb_streams[i].format =
418 gb_camera_mbus_to_gb(streams[i].pixel_code);
419 }
420
Gjorgji Rosikopulos5b032712016-01-17 19:52:21 +0200421 if (*flags & GB_CAMERA_IN_FLAG_TEST)
422 gb_flags |= GB_CAMERA_CONFIGURE_STREAMS_TEST_ONLY;
423
424 ret = gb_camera_configure_streams(gcam, &gb_nstreams,
425 &gb_flags, gb_streams);
Gjorgji Rosikopulos3a8dba42016-01-13 21:52:38 +0200426 if (ret < 0)
427 goto done;
Gjorgji Rosikopulos5b032712016-01-17 19:52:21 +0200428 if (gb_nstreams > *nstreams) {
429 ret = -EINVAL;
430 goto done;
431 }
Gjorgji Rosikopulos3a8dba42016-01-13 21:52:38 +0200432
Gjorgji Rosikopulos5b032712016-01-17 19:52:21 +0200433 *flags = 0;
434 if (gb_flags & GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED)
435 *flags |= GB_CAMERA_OUT_FLAG_ADJUSTED;
436
437 for (i = 0; i < gb_nstreams; i++) {
Gjorgji Rosikopulos3a8dba42016-01-13 21:52:38 +0200438 streams[i].width = gb_streams[i].width;
439 streams[i].height = gb_streams[i].height;
440 streams[i].vc = gb_streams[i].vc;
441 streams[i].dt[0] = gb_streams[i].dt[0];
442 streams[i].dt[1] = gb_streams[i].dt[1];
443 streams[i].max_size = gb_streams[i].max_size;
444 streams[i].pixel_code =
445 gb_camera_gb_to_mbus(gb_streams[i].format);
446 }
Gjorgji Rosikopulos5b032712016-01-17 19:52:21 +0200447 *nstreams = gb_nstreams;
Gjorgji Rosikopulos3a8dba42016-01-13 21:52:38 +0200448
449done:
450 kfree(gb_streams);
451 return ret;
452}
453
454static int gb_camera_op_capture(void *priv, u32 request_id,
455 unsigned int streams, unsigned int num_frames,
456 size_t settings_size, const void *settings)
457{
458 return gb_camera_capture(priv, request_id, streams, num_frames,
459 settings_size, settings);
460}
461
462static int gb_camera_op_flush(void *priv, u32 *request_id)
463{
464 return gb_camera_flush(priv, request_id);
465}
466
467struct gb_camera_ops gb_cam_ops = {
468 .configure_streams = gb_camera_op_configure_streams,
469 .capture = gb_camera_op_capture,
470 .flush = gb_camera_op_flush,
471};
472
473static int gb_camera_register_intf_ops(struct gb_camera *gcam)
474{
475 return gb_camera_register(&gb_cam_ops, gcam);
476}
477
478/* -----------------------------------------------------------------------------
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200479 * DebugFS
480 */
481static ssize_t gb_camera_debugfs_capabilities(struct gb_camera *gcam,
482 char *buf, size_t len)
483{
484 return len;
485}
486
487static ssize_t gb_camera_debugfs_configure_streams(struct gb_camera *gcam,
488 char *buf, size_t len)
489{
490 struct gb_camera_debugfs_buffer *buffer =
491 &gcam->debugfs.buffers[GB_CAMERA_DEBUGFS_BUFFER_STREAMS];
492 struct gb_camera_stream_config *streams;
493 unsigned int nstreams;
Jacopo Mondib787d412016-01-08 18:13:20 +0200494 unsigned int flags;
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200495 unsigned int i;
496 char *token;
497 int ret;
498
499 /* Retrieve number of streams to configure */
Jacopo Mondib787d412016-01-08 18:13:20 +0200500 token = strsep(&buf, ";");
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200501 if (token == NULL)
502 return -EINVAL;
503
504 ret = kstrtouint(token, 10, &nstreams);
505 if (ret < 0)
506 return ret;
507
508 if (nstreams > GB_CAMERA_MAX_STREAMS)
509 return -EINVAL;
510
Jacopo Mondib787d412016-01-08 18:13:20 +0200511 token = strsep(&buf, ";");
512 if (token == NULL)
513 return -EINVAL;
514
515 ret = kstrtouint(token, 10, &flags);
516 if (ret < 0)
517 return ret;
518
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200519 /* For each stream to configure parse width, height and format */
520 streams = kzalloc(nstreams * sizeof(*streams), GFP_KERNEL);
521 if (!streams)
522 return -ENOMEM;
523
524 for (i = 0; i < nstreams; ++i) {
525 struct gb_camera_stream_config *stream = &streams[i];
526
527 /* width */
528 token = strsep(&buf, ";");
529 if (token == NULL) {
530 ret = -EINVAL;
531 goto done;
532 }
533 ret = kstrtouint(token, 10, &stream->width);
534 if (ret < 0)
535 goto done;
536
537 /* height */
538 token = strsep(&buf, ";");
539 if (token == NULL)
540 goto done;
541
542 ret = kstrtouint(token, 10, &stream->height);
543 if (ret < 0)
544 goto done;
545
546 /* Image format code */
547 token = strsep(&buf, ";");
548 if (token == NULL)
549 goto done;
550
551 ret = kstrtouint(token, 16, &stream->format);
552 if (ret < 0)
553 goto done;
554 }
555
Laurent Pinchart40684872016-01-15 01:33:55 +0200556 ret = gb_camera_configure_streams(gcam, &nstreams, &flags, streams);
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200557 if (ret < 0)
558 goto done;
559
Laurent Pinchart40684872016-01-15 01:33:55 +0200560 buffer->length = sprintf(buffer->data, "%u;%u;", nstreams, flags);
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200561
562 for (i = 0; i < nstreams; ++i) {
563 struct gb_camera_stream_config *stream = &streams[i];
564
565 buffer->length += sprintf(buffer->data + buffer->length,
566 "%u;%u;%u;%u;%u;%u;%u;",
567 stream->width, stream->height,
568 stream->format, stream->vc,
569 stream->dt[0], stream->dt[1],
570 stream->max_size);
571 }
572
573 ret = len;
574
575done:
576 kfree(streams);
577 return ret;
578};
579
580static ssize_t gb_camera_debugfs_capture(struct gb_camera *gcam,
581 char *buf, size_t len)
582{
583 unsigned int request_id;
584 unsigned int streams_mask;
585 unsigned int num_frames;
586 char *token;
587 int ret;
588
589 /* Request id */
590 token = strsep(&buf, ";");
591 if (token == NULL)
592 return -EINVAL;
593 ret = kstrtouint(token, 10, &request_id);
594 if (ret < 0)
595 return ret;
596
597 /* Stream mask */
598 token = strsep(&buf, ";");
599 if (token == NULL)
600 return -EINVAL;
601 ret = kstrtouint(token, 16, &streams_mask);
602 if (ret < 0)
603 return ret;
604
605 /* number of frames */
606 token = strsep(&buf, ";");
607 if (token == NULL)
608 return -EINVAL;
609 ret = kstrtouint(token, 10, &num_frames);
610 if (ret < 0)
611 return ret;
612
613 ret = gb_camera_capture(gcam, request_id, streams_mask, num_frames, 0,
614 NULL);
615 if (ret < 0)
616 return ret;
617
618 return len;
619}
620
621static ssize_t gb_camera_debugfs_flush(struct gb_camera *gcam,
622 char *buf, size_t len)
623{
624 struct gb_camera_debugfs_buffer *buffer =
625 &gcam->debugfs.buffers[GB_CAMERA_DEBUGFS_BUFFER_FLUSH];
626 unsigned int req_id;
627 int ret;
628
629 ret = gb_camera_flush(gcam, &req_id);
630 if (ret < 0)
631 return ret;
632
633 buffer->length = sprintf(buffer->data, "%u", req_id);
634
635 return len;
636}
637
638struct gb_camera_debugfs_entry {
639 const char *name;
640 unsigned int mask;
641 unsigned int buffer;
642 ssize_t (*execute)(struct gb_camera *gcam, char *buf, size_t len);
643};
644
645static const struct gb_camera_debugfs_entry gb_camera_debugfs_entries[] = {
646 {
647 .name = "capabilities",
648 .mask = S_IFREG | S_IRUGO,
649 .buffer = GB_CAMERA_DEBUGFS_BUFFER_CAPABILITIES,
650 .execute = gb_camera_debugfs_capabilities,
651 }, {
652 .name = "configure_streams",
653 .mask = S_IFREG | S_IRUGO | S_IWUGO,
654 .buffer = GB_CAMERA_DEBUGFS_BUFFER_STREAMS,
655 .execute = gb_camera_debugfs_configure_streams,
656 }, {
657 .name = "capture",
658 .mask = S_IFREG | S_IRUGO | S_IWUGO,
659 .buffer = GB_CAMERA_DEBUGFS_BUFFER_CAPTURE,
660 .execute = gb_camera_debugfs_capture,
661 }, {
662 .name = "flush",
663 .mask = S_IFREG | S_IRUGO | S_IWUGO,
664 .buffer = GB_CAMERA_DEBUGFS_BUFFER_FLUSH,
665 .execute = gb_camera_debugfs_flush,
666 },
667};
668
669static ssize_t gb_camera_debugfs_read(struct file *file, char __user *buf,
670 size_t len, loff_t *offset)
671{
672 const struct gb_camera_debugfs_entry *op = file->private_data;
673 struct gb_camera *gcam = file->f_inode->i_private;
674 struct gb_camera_debugfs_buffer *buffer;
675 ssize_t ret;
676
677 /* For read-only entries the operation is triggered by a read. */
678 if (!(op->mask & S_IWUGO)) {
679 ret = op->execute(gcam, NULL, 0);
680 if (ret < 0)
681 return ret;
682 }
683
684 buffer = &gcam->debugfs.buffers[op->buffer];
685
686 return simple_read_from_buffer(buf, len, offset, buffer->data,
687 buffer->length);
688}
689
690static ssize_t gb_camera_debugfs_write(struct file *file,
691 const char __user *buf, size_t len,
692 loff_t *offset)
693{
694 const struct gb_camera_debugfs_entry *op = file->private_data;
695 struct gb_camera *gcam = file->f_inode->i_private;
696 ssize_t ret;
697 char *kbuf;
698
699 if (len > 1024)
700 return -EINVAL;
701
702 kbuf = kmalloc(len + 1, GFP_KERNEL);
703 if (kbuf == NULL)
704 return -ENOMEM;
705
706 if (copy_from_user(kbuf, buf, len)) {
707 ret = -EFAULT;
708 goto done;
709 }
710
711 kbuf[len] = '\0';
712
713 ret = op->execute(gcam, kbuf, len);
714
715done:
716 kfree(kbuf);
717 return ret;
718}
719
720static int gb_camera_debugfs_open(struct inode *inode, struct file *file)
721{
722 unsigned int i;
723
724 for (i = 0; i < ARRAY_SIZE(gb_camera_debugfs_entries); ++i) {
725 const struct gb_camera_debugfs_entry *entry =
726 &gb_camera_debugfs_entries[i];
727
Greg Kroah-Hartman4dda7442015-12-14 18:33:19 -0800728 if (!strcmp(file->f_path.dentry->d_iname, entry->name)) {
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200729 file->private_data = (void *)entry;
730 break;
731 }
732 }
733
734 return 0;
735}
736
737static const struct file_operations gb_camera_debugfs_ops = {
738 .open = gb_camera_debugfs_open,
739 .read = gb_camera_debugfs_read,
740 .write = gb_camera_debugfs_write,
741};
742
743static int gb_camera_debugfs_init(struct gb_camera *gcam)
744{
745 struct gb_connection *connection = gcam->connection;
746 char dirname[27];
747 unsigned int i;
748
749 /*
750 * Create root debugfs entry and a file entry for each camera operation.
751 */
752 snprintf(dirname, 27, "camera-%u.%u", connection->intf->interface_id,
753 connection->bundle->id);
754
755 gcam->debugfs.root = debugfs_create_dir(dirname, gb_debugfs_get());
756 if (IS_ERR(gcam->debugfs.root)) {
757 gcam_err(gcam, "debugfs root create failed (%ld)\n",
758 PTR_ERR(gcam->debugfs.root));
759 return PTR_ERR(gcam->debugfs.root);
760 }
761
762 gcam->debugfs.buffers = vmalloc(sizeof(*gcam->debugfs.buffers) *
763 GB_CAMERA_DEBUGFS_BUFFER_MAX);
764 if (!gcam->debugfs.buffers)
765 return -ENOMEM;
766
767 for (i = 0; i < ARRAY_SIZE(gb_camera_debugfs_entries); ++i) {
768 const struct gb_camera_debugfs_entry *entry =
769 &gb_camera_debugfs_entries[i];
770 struct dentry *dentry;
771
772 gcam->debugfs.buffers[i].length = 0;
773
774 dentry = debugfs_create_file(entry->name, entry->mask,
775 gcam->debugfs.root, gcam,
776 &gb_camera_debugfs_ops);
777 if (IS_ERR(dentry)) {
778 gcam_err(gcam,
779 "debugfs operation %s create failed (%ld)\n",
780 entry->name, PTR_ERR(gcam->debugfs.root));
781 return PTR_ERR(dentry);
782 }
783 }
784
785 return 0;
786}
787
788static void gb_camera_debugfs_cleanup(struct gb_camera *gcam)
789{
790 if (gcam->debugfs.root)
791 debugfs_remove_recursive(gcam->debugfs.root);
792
793 vfree(gcam->debugfs.buffers);
794}
795
796/* -----------------------------------------------------------------------------
797 * Init & Cleanup
798 */
799
800static void gb_camera_cleanup(struct gb_camera *gcam)
801{
802 gb_camera_debugfs_cleanup(gcam);
803
804 if (gcam->data_connected) {
805 struct gb_interface *intf = gcam->connection->intf;
806 struct gb_svc *svc = gcam->connection->hd->svc;
807
808 gb_svc_connection_destroy(svc, intf->interface_id,
809 ES2_APB_CDSI0_CPORT, svc->ap_intf_id,
810 ES2_APB_CDSI1_CPORT);
811 }
812
813 kfree(gcam);
814}
815
816static int gb_camera_connection_init(struct gb_connection *connection)
817{
818 struct gb_svc *svc = connection->hd->svc;
819 struct gb_camera *gcam;
820 int ret;
821
822 gcam = kzalloc(sizeof(*gcam), GFP_KERNEL);
823 if (!gcam)
824 return -ENOMEM;
825
826 gcam->connection = connection;
827 connection->private = gcam;
828
829 /*
830 * Create the data connection between camera module CDSI0 and APB CDS1.
831 * The CPort IDs are hardcoded by the ES2 bridges.
832 */
833 ret = gb_svc_connection_create(svc, connection->intf->interface_id,
834 ES2_APB_CDSI0_CPORT, svc->ap_intf_id,
835 ES2_APB_CDSI1_CPORT, false);
836 if (ret < 0)
837 goto error;
838
Johan Hovold41c23952015-12-30 11:23:51 +0100839 gcam->data_connected = true;
840
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200841 ret = gb_camera_debugfs_init(gcam);
842 if (ret < 0)
843 goto error;
844
Gjorgji Rosikopulos3a8dba42016-01-13 21:52:38 +0200845 ret = gb_camera_register_intf_ops(gcam);
846 if (ret < 0)
847 goto error;
848
Laurent Pinchart3265eda2015-12-15 03:18:06 +0200849 return 0;
850
851error:
852 gb_camera_cleanup(gcam);
853 return ret;
854}
855
856static void gb_camera_connection_exit(struct gb_connection *connection)
857{
858 struct gb_camera *gcam = connection->private;
859
860 gb_camera_cleanup(gcam);
861}
862
863static struct gb_protocol camera_protocol = {
864 .name = "camera",
865 .id = GREYBUS_PROTOCOL_CAMERA_MGMT,
866 .major = GB_CAMERA_VERSION_MAJOR,
867 .minor = GB_CAMERA_VERSION_MINOR,
868 .connection_init = gb_camera_connection_init,
869 .connection_exit = gb_camera_connection_exit,
870 .request_recv = gb_camera_event_recv,
871};
872
873gb_protocol_driver(&camera_protocol);
874
875MODULE_LICENSE("GPL v2");