1/*
2Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are
6met:
7    * Redistributions of source code must retain the above copyright
8      notice, this list of conditions and the following disclaimer.
9    * Redistributions in binary form must reproduce the above
10      copyright notice, this list of conditions and the following
11      disclaimer in the documentation and/or other materials provided
12      with the distribution.
13    * Neither the name of The Linux Foundation nor the names of its
14      contributors may be used to endorse or promote products derived
15      from this software without specific prior written permission.
16
17THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*/
29
30#include "mm_qcamera_dbg.h"
31#include "mm_qcamera_app.h"
32
33static uint32_t rdi_len = 0;
34
35static void mm_app_rdi_dump_frame(mm_camera_buf_def_t *frame,
36                                  char *name,
37                                  char *ext,
38                                  int frame_idx)
39{
40    char file_name[64];
41    int file_fd;
42    int i;
43    if (frame != NULL) {
44        snprintf(file_name, sizeof(file_name), "/data/%s_%03d.%s", name, frame_idx, ext);
45        file_fd = open(file_name, O_RDWR | O_CREAT, 0777);
46        if (file_fd < 0) {
47            CDBG_ERROR("%s: cannot open file %s \n", __func__, file_name);
48        } else {
49            for (i = 0; i < frame->num_planes; i++) {
50                write(file_fd,
51                      (uint8_t *)frame->buffer + frame->planes[i].data_offset,
52                      rdi_len);
53            }
54
55            close(file_fd);
56            CDBG("dump %s", file_name);
57        }
58    }
59}
60
61static void mm_app_rdi_notify_cb(mm_camera_super_buf_t *bufs,
62                                 void *user_data)
63{
64    char file_name[64];
65    mm_camera_buf_def_t *frame = bufs->bufs[0];
66    mm_camera_test_obj_t *pme = (mm_camera_test_obj_t *)user_data;
67
68    CDBG("%s: BEGIN - length=%d, frame idx = %d stream_id=%d\n",
69         __func__, frame->frame_len, frame->frame_idx, frame->stream_id);
70    snprintf(file_name, sizeof(file_name), "RDI_dump_%d", pme->cam->camera_handle);
71    mm_app_rdi_dump_frame(frame, file_name, "raw", frame->frame_idx);
72
73    if (MM_CAMERA_OK != pme->cam->ops->qbuf(bufs->camera_handle,
74                                            bufs->ch_id,
75                                            frame)) {
76        CDBG_ERROR("%s: Failed in RDI Qbuf\n", __func__);
77    }
78    mm_app_cache_ops((mm_camera_app_meminfo_t *)frame->mem_info,
79                     ION_IOC_INV_CACHES);
80
81    CDBG("%s: END\n", __func__);
82}
83
84mm_camera_stream_t * mm_app_add_rdi_stream(mm_camera_test_obj_t *test_obj,
85                                               mm_camera_channel_t *channel,
86                                               mm_camera_buf_notify_t stream_cb,
87                                               void *userdata,
88                                               uint8_t num_bufs,
89                                               uint8_t num_burst)
90{
91    int rc = MM_CAMERA_OK;
92    int i;
93    mm_camera_stream_t *stream = NULL;
94    cam_capability_t *cam_cap = (cam_capability_t *)(test_obj->cap_buf.buf.buffer);
95    cam_format_t fmt = CAM_FORMAT_MAX;
96    cam_stream_buf_plane_info_t *buf_planes;
97
98    stream = mm_app_add_stream(test_obj, channel);
99    if (NULL == stream) {
100        CDBG_ERROR("%s: add stream failed\n", __func__);
101        return NULL;
102    }
103
104    CDBG_ERROR("%s: raw_dim w:%d height:%d\n", __func__, cam_cap->raw_dim.width, cam_cap->raw_dim.height);
105    for (i = 0;i < cam_cap->supported_raw_fmt_cnt;i++) {
106        CDBG_ERROR("%s: supported_raw_fmts[%d]=%d\n", __func__, i, cam_cap->supported_raw_fmts[i]);
107        if (CAM_FORMAT_BAYER_MIPI_RAW_8BPP_GBRG <= cam_cap->supported_raw_fmts[i] &&
108            CAM_FORMAT_BAYER_MIPI_RAW_12BPP_BGGR >= cam_cap->supported_raw_fmts[i])
109        {
110            fmt = cam_cap->supported_raw_fmts[i];
111            CDBG_ERROR("%s: fmt=%d\n", __func__, fmt);
112        }
113    }
114
115    if (CAM_FORMAT_MAX == fmt) {
116        CDBG_ERROR("%s: rdi format not supported\n", __func__);
117        return NULL;
118    }
119
120    stream->s_config.mem_vtbl.get_bufs = mm_app_stream_initbuf;
121    stream->s_config.mem_vtbl.put_bufs = mm_app_stream_deinitbuf;
122    stream->s_config.mem_vtbl.clean_invalidate_buf =
123      mm_app_stream_clean_invalidate_buf;
124    stream->s_config.mem_vtbl.invalidate_buf = mm_app_stream_invalidate_buf;
125    stream->s_config.mem_vtbl.user_data = (void *)stream;
126    stream->s_config.stream_cb = stream_cb;
127    stream->s_config.userdata = userdata;
128    stream->num_of_bufs = num_bufs;
129
130    stream->s_config.stream_info = (cam_stream_info_t *)stream->s_info_buf.buf.buffer;
131    memset(stream->s_config.stream_info, 0, sizeof(cam_stream_info_t));
132    stream->s_config.stream_info->stream_type = CAM_STREAM_TYPE_RAW;
133    if (num_burst == 0) {
134        stream->s_config.stream_info->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS;
135    } else {
136        stream->s_config.stream_info->streaming_mode = CAM_STREAMING_MODE_BURST;
137        stream->s_config.stream_info->num_of_burst = num_burst;
138    }
139    stream->s_config.stream_info->fmt = fmt;
140    stream->s_config.stream_info->dim.width = cam_cap->raw_dim.width;
141    stream->s_config.stream_info->dim.height = cam_cap->raw_dim.height;
142    stream->s_config.padding_info = cam_cap->padding_info;
143
144    rc = mm_app_config_stream(test_obj, channel, stream, &stream->s_config);
145    if (MM_CAMERA_OK != rc) {
146        CDBG_ERROR("%s:config rdi stream err=%d\n", __func__, rc);
147        return NULL;
148    }
149
150    buf_planes = &stream->s_config.stream_info->buf_planes;
151    rdi_len = buf_planes->plane_info.mp[0].len;
152    CDBG("%s: plane_info %dx%d len:%d frame_len:%d\n", __func__,
153        buf_planes->plane_info.mp[0].stride, buf_planes->plane_info.mp[0].scanline,
154        buf_planes->plane_info.mp[0].len, buf_planes->plane_info.frame_len);
155
156    return stream;
157}
158
159mm_camera_stream_t * mm_app_add_rdi_snapshot_stream(mm_camera_test_obj_t *test_obj,
160                                                mm_camera_channel_t *channel,
161                                                mm_camera_buf_notify_t stream_cb,
162                                                void *userdata,
163                                                uint8_t num_bufs,
164                                                uint8_t num_burst)
165{
166    int rc = MM_CAMERA_OK;
167    mm_camera_stream_t *stream = NULL;
168    cam_capability_t *cam_cap = (cam_capability_t *)(test_obj->cap_buf.buf.buffer);
169
170    stream = mm_app_add_stream(test_obj, channel);
171    if (NULL == stream) {
172        CDBG_ERROR("%s: add stream failed\n", __func__);
173        return NULL;
174    }
175
176    stream->s_config.mem_vtbl.get_bufs = mm_app_stream_initbuf;
177    stream->s_config.mem_vtbl.put_bufs = mm_app_stream_deinitbuf;
178    stream->s_config.mem_vtbl.clean_invalidate_buf =
179      mm_app_stream_clean_invalidate_buf;
180    stream->s_config.mem_vtbl.invalidate_buf = mm_app_stream_invalidate_buf;
181    stream->s_config.mem_vtbl.user_data = (void *)stream;
182    stream->s_config.stream_cb = stream_cb;
183    stream->s_config.userdata = userdata;
184    stream->num_of_bufs = num_bufs;
185
186    stream->s_config.stream_info = (cam_stream_info_t *)stream->s_info_buf.buf.buffer;
187    memset(stream->s_config.stream_info, 0, sizeof(cam_stream_info_t));
188    stream->s_config.stream_info->stream_type = CAM_STREAM_TYPE_SNAPSHOT;
189    if (num_burst == 0) {
190        stream->s_config.stream_info->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS;
191    } else {
192        stream->s_config.stream_info->streaming_mode = CAM_STREAMING_MODE_BURST;
193        stream->s_config.stream_info->num_of_burst = num_burst;
194    }
195    stream->s_config.stream_info->fmt = DEFAULT_SNAPSHOT_FORMAT;
196    stream->s_config.stream_info->dim.width = DEFAULT_SNAPSHOT_WIDTH;
197    stream->s_config.stream_info->dim.height = DEFAULT_SNAPSHOT_HEIGHT;
198    stream->s_config.padding_info = cam_cap->padding_info;
199
200    rc = mm_app_config_stream(test_obj, channel, stream, &stream->s_config);
201    if (MM_CAMERA_OK != rc) {
202        CDBG_ERROR("%s:config rdi stream err=%d\n", __func__, rc);
203        return NULL;
204    }
205
206    return stream;
207}
208
209mm_camera_channel_t * mm_app_add_rdi_channel(mm_camera_test_obj_t *test_obj, uint8_t num_burst)
210{
211    mm_camera_channel_t *channel = NULL;
212    mm_camera_stream_t *stream = NULL;
213
214    channel = mm_app_add_channel(test_obj,
215                                 MM_CHANNEL_TYPE_RDI,
216                                 NULL,
217                                 NULL,
218                                 NULL);
219    if (NULL == channel) {
220        CDBG_ERROR("%s: add channel failed", __func__);
221        return NULL;
222    }
223
224    stream = mm_app_add_rdi_stream(test_obj,
225                                       channel,
226                                       mm_app_rdi_notify_cb,
227                                       (void *)test_obj,
228                                       RDI_BUF_NUM,
229                                       num_burst);
230    if (NULL == stream) {
231        CDBG_ERROR("%s: add stream failed\n", __func__);
232        mm_app_del_channel(test_obj, channel);
233        return NULL;
234    }
235
236    CDBG("%s: channel=%d stream=%d\n", __func__, channel->ch_id, stream->s_id);
237    return channel;
238}
239
240int mm_app_stop_and_del_rdi_channel(mm_camera_test_obj_t *test_obj,
241                                mm_camera_channel_t *channel)
242{
243    int rc = MM_CAMERA_OK;
244    mm_camera_stream_t *stream = NULL;
245    uint8_t i;
246
247    rc = mm_app_stop_channel(test_obj, channel);
248    if (MM_CAMERA_OK != rc) {
249        CDBG_ERROR("%s:Stop RDI failed rc=%d\n", __func__, rc);
250    }
251
252    for (i = 0; i < channel->num_streams; i++) {
253        stream = &channel->streams[i];
254        rc = mm_app_del_stream(test_obj, channel, stream);
255        if (MM_CAMERA_OK != rc) {
256            CDBG_ERROR("%s:del stream(%d) failed rc=%d\n", __func__, i, rc);
257        }
258    }
259
260    rc = mm_app_del_channel(test_obj, channel);
261    if (MM_CAMERA_OK != rc) {
262        CDBG_ERROR("%s:delete channel failed rc=%d\n", __func__, rc);
263    }
264
265    return rc;
266}
267
268int mm_app_start_rdi(mm_camera_test_obj_t *test_obj, uint8_t num_burst)
269{
270    int rc = MM_CAMERA_OK;
271    mm_camera_channel_t *channel = NULL;
272
273    channel = mm_app_add_rdi_channel(test_obj, num_burst);
274    if (NULL == channel) {
275        CDBG_ERROR("%s: add channel failed", __func__);
276        return -MM_CAMERA_E_GENERAL;
277    }
278
279    rc = mm_app_start_channel(test_obj, channel);
280    if (MM_CAMERA_OK != rc) {
281        CDBG_ERROR("%s:start rdi failed rc=%d\n", __func__, rc);
282        mm_app_del_channel(test_obj, channel);
283        return rc;
284    }
285
286    return rc;
287}
288
289int mm_app_stop_rdi(mm_camera_test_obj_t *test_obj)
290{
291    int rc = MM_CAMERA_OK;
292
293    mm_camera_channel_t *channel =
294        mm_app_get_channel_by_type(test_obj, MM_CHANNEL_TYPE_RDI);
295
296    rc = mm_app_stop_and_del_rdi_channel(test_obj, channel);
297    if (MM_CAMERA_OK != rc) {
298        CDBG_ERROR("%s:Stop RDI failed rc=%d\n", __func__, rc);
299    }
300
301    return rc;
302}
303
304