xref: /OK3568_Linux_fs/external/camera_engine_rkaiq/rkaiq/hwi/FlashLight.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  *  Copyright (c) 2019 Rockchip Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 
18 #include "FlashLight.h"
19 #include "xcam_log.h"
20 #include "linux/rk-led-flash.h"
21 
22 namespace RkCam {
23 
FlashLightHw(std::string name[],int num)24 FlashLightHw::FlashLightHw(std::string name[], int num)
25 {
26     if (num >= FLASH_MAX_NUM) {
27         LOGE_CAMHW_SUBM(FL_SUBM, "not support flash num %d", num);
28         return ;
29     }
30 
31     _dev_num = 0;
32     for (int i = 0 ; i < num; i++) {
33         _fl_device[i] = new V4l2SubDevice(name[i].c_str());
34         _dev_num++;
35     }
36     _active_fl_num = 0;
37     _keep_status = false;
38     xcam_mem_clear (_flash_settings);
39 }
40 
~FlashLightHw()41 FlashLightHw::~FlashLightHw()
42 {
43 
44 }
45 
46 XCamReturn
init(int active_num)47 FlashLightHw::init(int active_num)
48 {
49     XCAM_ASSERT (active_num <= _dev_num);
50 
51     for (int i = 0 ; i < active_num; i++) {
52         _fl_device[i]->open();
53         _active_fl_num++;
54     }
55 
56     get_flash_info ();
57 
58     return XCAM_RETURN_NO_ERROR;
59 }
60 
61 XCamReturn
deinit()62 FlashLightHw::deinit()
63 {
64     if (!_keep_status) {
65         v4l_set_params(RK_AIQ_FLASH_MODE_OFF, 0, 0, false);
66         xcam_mem_clear (_flash_settings);
67     }
68     for (int i = 0 ; i < _active_fl_num; i++) {
69         _fl_device[i]->close();
70     }
71     _active_fl_num = 0;
72 
73     return XCAM_RETURN_NO_ERROR;
74 }
75 
76 XCamReturn
start()77 FlashLightHw::start()
78 {
79     for (int i = 0 ; i < _active_fl_num; i++) {
80         _fl_device[i]->start();
81     }
82 
83     return XCAM_RETURN_NO_ERROR;
84 }
85 
86 XCamReturn
stop()87 FlashLightHw::stop()
88 {
89     if (!_keep_status) {
90         v4l_set_params(RK_AIQ_FLASH_MODE_OFF, 0, 0, false);
91         xcam_mem_clear (_flash_settings);
92     }
93     for (int i = 0 ; i < _active_fl_num; i++) {
94         _fl_device[i]->stop();
95     }
96 
97     return XCAM_RETURN_NO_ERROR;
98 }
99 
100 XCamReturn
set_params(rk_aiq_flash_setting_t & flash_settings)101 FlashLightHw::set_params(rk_aiq_flash_setting_t& flash_settings)
102 {
103     XCamReturn ret = XCAM_RETURN_NO_ERROR;
104     // set flash if needed
105     rk_aiq_flash_setting_t* old_flash_settings = &_flash_settings;
106     if ((old_flash_settings->flash_mode != flash_settings.flash_mode) ||
107             (old_flash_settings->strobe != flash_settings.strobe) ||
108             (old_flash_settings->power[0] != flash_settings.power[0]) ||
109             (old_flash_settings->power[1] != flash_settings.power[1])
110        ) {
111        LOGD_CAMHW_SUBM(FL_SUBM, "flash_settings: mode:%d,power:%f,timeout_ms:%d,strobe:%d",
112                              flash_settings.flash_mode, flash_settings.power[0],
113                              flash_settings.timeout_ms, flash_settings.strobe);
114         ret = v4l_set_params(flash_settings.flash_mode, flash_settings.power,
115                              flash_settings.timeout_ms, flash_settings.strobe);
116         if (!ret)
117             _flash_settings = flash_settings;
118     }
119 
120     return ret;
121 }
122 
123 XCamReturn
get_status(rk_aiq_flash_setting_t & flash_settings,uint32_t frame_id)124 FlashLightHw::get_status (rk_aiq_flash_setting_t& flash_settings, uint32_t frame_id)
125 {
126     if (!_active_fl_num)
127         return XCAM_RETURN_ERROR_FAILED;
128 
129     flash_settings = _flash_settings;
130 
131     if (_fl_device[0].ptr()) {
132         struct timeval flash_time;
133 
134         if (_fl_device[0]->io_control (RK_VIDIOC_FLASH_TIMEINFO, &flash_time) < 0) {
135             LOGE_CAMHW_SUBM(FL_SUBM, " get RK_VIDIOC_FLASH_TIMEINFO failed. cmd = 0x%x", RK_VIDIOC_FLASH_TIMEINFO);
136             /* return XCAM_RETURN_ERROR_IOCTL; */
137         }
138         flash_settings.effect_ts = (int64_t)flash_time.tv_sec * 1000 * 1000 +
139                                    (int64_t)flash_time.tv_usec;
140         LOGD_CAMHW_SUBM(FL_SUBM, "frameid %u, get RK_VIDIOC_FLASH_TIMEINFO flash ts %lld",
141                         frame_id, flash_settings.effect_ts);
142     }
143 
144     // for the following case:
145     // 1) set to flash mode
146     // 2) one flash power set to 0
147     // then we can't get the effect ts from the node which power set to 0
148     if (_fl_device[1].ptr() && flash_settings.effect_ts == 0 &&
149             flash_settings.power[0] != flash_settings.power[1]) {
150         struct timeval flash_time;
151 
152         if (_fl_device[1]->io_control (RK_VIDIOC_FLASH_TIMEINFO, &flash_time) < 0) {
153             LOGE_CAMHW_SUBM(FL_SUBM, " get RK_VIDIOC_FLASH_TIMEINFO failed. cmd = 0x%x", RK_VIDIOC_FLASH_TIMEINFO);
154             /* return XCAM_RETURN_ERROR_IOCTL; */
155         }
156         flash_settings.effect_ts = (int64_t)flash_time.tv_sec * 1000 * 1000 +
157                                    (int64_t)flash_time.tv_usec;
158         LOGD_CAMHW_SUBM(FL_SUBM, "frameid %u, get RK_VIDIOC_FLASH_TIMEINFO flash ts %lld",
159                         frame_id, flash_settings.effect_ts);
160     }
161 
162     return XCAM_RETURN_NO_ERROR;
163 }
164 
165 XCamReturn
v4l_set_params(int fl_mode,float fl_intensity[],int fl_timeout,int fl_on)166 FlashLightHw::v4l_set_params(int fl_mode, float fl_intensity[], int fl_timeout, int fl_on)
167 {
168     struct v4l2_control control;
169     int fl_v4l_mode;
170     int i = 0;
171 #define set_fl_contol_to_dev(fl_dev,control_id,val) \
172         {\
173             xcam_mem_clear (control); \
174             control.id = control_id; \
175             control.value = val; \
176             if (fl_dev->io_control (VIDIOC_S_CTRL, &control) < 0) { \
177                 LOGE_CAMHW_SUBM(FL_SUBM, " set fl %s to %d failed", #control_id, val); \
178                 return XCAM_RETURN_ERROR_IOCTL; \
179             } \
180             LOGD_CAMHW_SUBM(FL_SUBM, "set fl %p, cid %s to %d, success",\
181                             fl_dev.ptr(), #control_id, val); \
182         }\
183 
184     if (fl_mode == RK_AIQ_FLASH_MODE_OFF)
185         fl_v4l_mode = V4L2_FLASH_LED_MODE_NONE;
186     else if (fl_mode == RK_AIQ_FLASH_MODE_FLASH || fl_mode == RK_AIQ_FLASH_MODE_FLASH_MAIN)
187         fl_v4l_mode = V4L2_FLASH_LED_MODE_FLASH;
188     else if (fl_mode == RK_AIQ_FLASH_MODE_FLASH_PRE || fl_mode ==  RK_AIQ_FLASH_MODE_TORCH)
189         fl_v4l_mode = V4L2_FLASH_LED_MODE_TORCH;
190     else {
191         LOGE_CAMHW_SUBM(FL_SUBM, " set fl to mode  %d failed", fl_mode);
192         return XCAM_RETURN_ERROR_PARAM;
193     }
194 
195     SmartPtr<V4l2SubDevice> fl_device;
196 
197     if (fl_v4l_mode == V4L2_FLASH_LED_MODE_NONE) {
198         for (i = 0; i < _active_fl_num; i++) {
199             fl_device = _fl_device[i];
200             set_fl_contol_to_dev(fl_device, V4L2_CID_FLASH_LED_MODE, V4L2_FLASH_LED_MODE_NONE);
201         }
202     } else if (fl_v4l_mode == V4L2_FLASH_LED_MODE_FLASH) {
203         for (i = 0; i < _active_fl_num; i++) {
204             fl_device = _fl_device[i];
205             set_fl_contol_to_dev(fl_device, V4L2_CID_FLASH_LED_MODE, V4L2_FLASH_LED_MODE_FLASH);
206             set_fl_contol_to_dev(fl_device, V4L2_CID_FLASH_TIMEOUT, fl_timeout * 1000);
207             if (_v4l_flash_info[i].fl_strth_adj_enable) {
208                 int flash_power =
209                     fl_intensity[i] * (_v4l_flash_info[i].flash_power_info[RK_AIQ_V4L_FLASH_QUERY_TYPE_E_MAX]);
210                 set_fl_contol_to_dev(fl_device, V4L2_CID_FLASH_INTENSITY, flash_power);
211                 LOGD_CAMHW_SUBM(FL_SUBM, "set flash: flash:%f max:%d set:%d\n",
212                                 fl_intensity[i],
213                                 _v4l_flash_info[i].flash_power_info[RK_AIQ_V4L_FLASH_QUERY_TYPE_E_MAX],
214                                 flash_power);
215             }
216         }
217 
218         // shoude flash on all finally
219         for (i = 0; i < _active_fl_num; i++) {
220             set_fl_contol_to_dev(fl_device,
221                                  fl_on ? V4L2_CID_FLASH_STROBE : V4L2_CID_FLASH_STROBE_STOP, 0);
222         }
223     } else if (fl_v4l_mode == V4L2_FLASH_LED_MODE_TORCH) {
224         for (i = 0; i < _active_fl_num; i++) {
225             fl_device = _fl_device[i];
226             if (_v4l_flash_info[i].tc_strth_adj_enable) {
227                 int torch_power =
228                     fl_intensity[i] * (_v4l_flash_info[i].torch_power_info[RK_AIQ_V4L_FLASH_QUERY_TYPE_E_MAX]);
229                 set_fl_contol_to_dev(fl_device, V4L2_CID_FLASH_TORCH_INTENSITY, torch_power);
230                 LOGD_CAMHW_SUBM(FL_SUBM, "set flash: torch:%f max:%d set:%d\n",
231                                 fl_intensity[i],
232                                 _v4l_flash_info[i].torch_power_info[RK_AIQ_V4L_FLASH_QUERY_TYPE_E_MAX],
233                                 torch_power);
234             }
235             set_fl_contol_to_dev(fl_device, V4L2_CID_FLASH_LED_MODE, V4L2_FLASH_LED_MODE_TORCH);
236         }
237     } else {
238         LOGE_CAMHW_SUBM(FL_SUBM, "|||set_3a_fl error fl mode %d", fl_mode);
239         return XCAM_RETURN_ERROR_PARAM;
240     }
241 
242     return XCAM_RETURN_NO_ERROR;
243 }
244 
245 int
get_flash_info()246 FlashLightHw::get_flash_info ()
247 {
248     struct v4l2_queryctrl ctrl;
249     int flash_power, torch_power;
250     SmartPtr<V4l2SubDevice> fl_device;
251 
252     for (int i = 0; i < _active_fl_num; i++) {
253         fl_device = _fl_device[i];
254 
255         memset(&ctrl, 0, sizeof(ctrl));
256         ctrl.id = V4L2_CID_FLASH_INTENSITY;
257         if (fl_device->io_control(VIDIOC_QUERYCTRL, &ctrl) < 0) {
258             LOGE_CAMHW_SUBM(FL_SUBM, "query V4L2_CID_FLASH_INTENSITY failed. cmd = 0x%x",
259                             V4L2_CID_FLASH_INTENSITY);
260             return -errno;
261         }
262 
263         _v4l_flash_info[i].flash_power_info[RK_AIQ_V4L_FLASH_QUERY_TYPE_E_MIN] =
264             ctrl.minimum;
265         _v4l_flash_info[i].flash_power_info[RK_AIQ_V4L_FLASH_QUERY_TYPE_E_MAX] =
266             ctrl.maximum;
267         _v4l_flash_info[i].flash_power_info[RK_AIQ_V4L_FLASH_QUERY_TYPE_E_DEFAULT] =
268             ctrl.default_value;
269         _v4l_flash_info[i].flash_power_info[RK_AIQ_V4L_FLASH_QUERY_TYPE_E_STEP] =
270             ctrl.step;
271         _v4l_flash_info[i].fl_strth_adj_enable = !(ctrl.flags & V4L2_CTRL_FLAG_READ_ONLY);
272 
273         LOGD_CAMHW_SUBM(FL_SUBM, "fl_dev[%d], flash power range:[%d,%d], adjust enable %d",
274                         i, ctrl.minimum, ctrl.maximum, _v4l_flash_info[i].fl_strth_adj_enable);
275 
276         memset(&ctrl, 0, sizeof(ctrl));
277         ctrl.id = V4L2_CID_FLASH_TORCH_INTENSITY;
278         if (fl_device->io_control(VIDIOC_QUERYCTRL, &ctrl) < 0) {
279             LOGE_CAMHW_SUBM(FL_SUBM, "query V4L2_CID_FLASH_TORCH_INTENSITY failed. cmd = 0x%x",
280                             V4L2_CID_FLASH_TORCH_INTENSITY);
281             return -errno;
282         }
283 
284         _v4l_flash_info[i].torch_power_info[RK_AIQ_V4L_FLASH_QUERY_TYPE_E_MIN] =
285             ctrl.minimum;
286         _v4l_flash_info[i].torch_power_info[RK_AIQ_V4L_FLASH_QUERY_TYPE_E_MAX] =
287             ctrl.maximum;
288         _v4l_flash_info[i].torch_power_info[RK_AIQ_V4L_FLASH_QUERY_TYPE_E_DEFAULT] =
289             ctrl.default_value;
290         _v4l_flash_info[i].torch_power_info[RK_AIQ_V4L_FLASH_QUERY_TYPE_E_STEP] =
291             ctrl.step;
292 
293         _v4l_flash_info[i].tc_strth_adj_enable = !(ctrl.flags & V4L2_CTRL_FLAG_READ_ONLY);
294 
295 
296         LOGD_CAMHW_SUBM(FL_SUBM, "fl_dev[%d], torch power range:[%d,%d], adjust enable %d",
297                         i, ctrl.minimum, ctrl.maximum, _v4l_flash_info[i].tc_strth_adj_enable);
298     }
299 
300     return XCAM_RETURN_NO_ERROR;
301 }
302 
303 }
304