camerad: simple BPS support (#34538)

* camerad: simple BPS support

* works

* cleanup

* lil more

---------

Co-authored-by: Comma Device <device@comma.ai>
pull/34540/head
Adeeb Shihadeh 3 months ago committed by GitHub
parent e31ae06959
commit 5b870c6f92
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      system/camerad/cameras/camera_common.cc
  2. 2
      system/camerad/cameras/camera_qcom2.cc
  3. 83
      system/camerad/cameras/spectra.cc
  4. 10
      system/camerad/cameras/spectra.h
  5. 2
      system/camerad/test/debug.sh

@ -64,11 +64,11 @@ void CameraBuf::init(cl_device_id device_id, cl_context context, SpectraCamera *
const SensorInfo *sensor = cam->sensor.get(); const SensorInfo *sensor = cam->sensor.get();
is_raw = cam->is_raw; is_raw = cam->output_type == ISP_RAW_OUTPUT;
frame_metadata = std::make_unique<FrameMetadata[]>(frame_buf_count); frame_metadata = std::make_unique<FrameMetadata[]>(frame_buf_count);
// RAW frames from ISP // RAW frames from ISP
if (is_raw) { if (cam->output_type != ISP_IFE_PROCESSED) {
camera_bufs_raw = std::make_unique<VisionBuf[]>(frame_buf_count); camera_bufs_raw = std::make_unique<VisionBuf[]>(frame_buf_count);
const int raw_frame_size = (sensor->frame_height + sensor->extra_height) * sensor->frame_stride; const int raw_frame_size = (sensor->frame_height + sensor->extra_height) * sensor->frame_stride;

@ -55,7 +55,7 @@ public:
float fl_pix = 0; float fl_pix = 0;
CameraState(SpectraMaster *master, const CameraConfig &config) : camera(master, config, config.stream_type == VISION_STREAM_ROAD) {}; CameraState(SpectraMaster *master, const CameraConfig &config) : camera(master, config, config.stream_type == VISION_STREAM_ROAD ? ISP_RAW_OUTPUT : ISP_IFE_PROCESSED) {};
~CameraState(); ~CameraState();
void init(VisionIpcServer *v, cl_device_id device_id, cl_context ctx); void init(VisionIpcServer *v, cl_device_id device_id, cl_context ctx);
void update_exposure_score(float desired_ev, int exp_t, int exp_g_idx, float exp_gain); void update_exposure_score(float desired_ev, int exp_t, int exp_g_idx, float exp_gain);

@ -234,14 +234,14 @@ void SpectraMaster::init() {
// *** SpectraCamera *** // *** SpectraCamera ***
SpectraCamera::SpectraCamera(SpectraMaster *master, const CameraConfig &config, bool raw) SpectraCamera::SpectraCamera(SpectraMaster *master, const CameraConfig &config, SpectraOutputType out)
: m(master), : m(master),
enabled(config.enabled), enabled(config.enabled),
cc(config), cc(config),
is_raw(raw) { output_type(out) {
mm.init(m->video0_fd); mm.init(m->video0_fd);
ife_buf_depth = is_raw ? 4 : VIPC_BUFFER_COUNT; ife_buf_depth = (out != ISP_IFE_PROCESSED) ? 4 : VIPC_BUFFER_COUNT;
assert(ife_buf_depth < MAX_IFE_BUFS); assert(ife_buf_depth < MAX_IFE_BUFS);
} }
@ -257,7 +257,7 @@ int SpectraCamera::clear_req_queue() {
req_mgr_flush_request.link_hdl = link_handle; req_mgr_flush_request.link_hdl = link_handle;
req_mgr_flush_request.flush_type = CAM_REQ_MGR_FLUSH_TYPE_ALL; req_mgr_flush_request.flush_type = CAM_REQ_MGR_FLUSH_TYPE_ALL;
int ret = do_cam_control(m->video0_fd, CAM_REQ_MGR_FLUSH_REQ, &req_mgr_flush_request, sizeof(req_mgr_flush_request)); int ret = do_cam_control(m->video0_fd, CAM_REQ_MGR_FLUSH_REQ, &req_mgr_flush_request, sizeof(req_mgr_flush_request));
// LOGD("flushed all req: %d", ret); LOGD("flushed all req: %d", ret);
for (int i = 0; i < MAX_IFE_BUFS; ++i) { for (int i = 0; i < MAX_IFE_BUFS; ++i) {
destroySyncObjectAt(i); destroySyncObjectAt(i);
@ -279,7 +279,7 @@ void SpectraCamera::camera_open(VisionIpcServer *v, cl_device_id device_id, cl_c
uv_height = VENUS_UV_SCANLINES(COLOR_FMT_NV12, sensor->frame_height); uv_height = VENUS_UV_SCANLINES(COLOR_FMT_NV12, sensor->frame_height);
uv_offset = stride*y_height; uv_offset = stride*y_height;
yuv_size = uv_offset + stride*uv_height; yuv_size = uv_offset + stride*uv_height;
if (!is_raw) { if (output_type != ISP_RAW_OUTPUT) {
uv_offset = ALIGNED_SIZE(uv_offset, 0x1000); uv_offset = ALIGNED_SIZE(uv_offset, 0x1000);
yuv_size = uv_offset + ALIGNED_SIZE(stride*uv_height, 0x1000); yuv_size = uv_offset + ALIGNED_SIZE(stride*uv_height, 0x1000);
} }
@ -288,7 +288,7 @@ void SpectraCamera::camera_open(VisionIpcServer *v, cl_device_id device_id, cl_c
open = true; open = true;
configISP(); configISP();
//configICP(); // needs the new AGNOS kernel if (output_type == ISP_BPS_PROCESSED) configICP();
configCSIPHY(); configCSIPHY();
linkDevices(); linkDevices();
@ -454,23 +454,24 @@ int SpectraCamera::sensors_init() {
return ret; return ret;
} }
void add_patch(void *ptr, int n, int32_t dst_hdl, uint32_t dst_offset, int32_t src_hdl, uint32_t src_offset) {
struct cam_patch_desc *p = (struct cam_patch_desc *)((unsigned char*)ptr + sizeof(struct cam_patch_desc)*n);
p->dst_buf_hdl = dst_hdl;
p->src_buf_hdl = src_hdl;
p->dst_offset = dst_offset;
p->src_offset = src_offset;
};
void SpectraCamera::config_bps(int idx, int request_id) { void SpectraCamera::config_bps(int idx, int request_id) {
/* /*
Handles per-frame BPS config. Handles per-frame BPS config.
* BPS = Bayer Processing Segment * BPS = Bayer Processing Segment
*/ */
(void)idx; (void)idx;
(void)request_id; (void)request_id;
} }
void add_patch(void *ptr, int n, int32_t dst_hdl, uint32_t dst_offset, int32_t src_hdl, uint32_t src_offset) {
struct cam_patch_desc *p = (struct cam_patch_desc *)((unsigned char*)ptr + sizeof(struct cam_patch_desc)*n);
p->dst_buf_hdl = dst_hdl;
p->src_buf_hdl = src_hdl;
p->dst_offset = dst_offset;
p->src_offset = src_offset;
};
void SpectraCamera::config_ife(int idx, int request_id, bool init) { void SpectraCamera::config_ife(int idx, int request_id, bool init) {
/* /*
Handles initial + per-frame IFE config. Handles initial + per-frame IFE config.
@ -509,6 +510,7 @@ void SpectraCamera::config_ife(int idx, int request_id, bool init) {
buf_desc[0].offset = ife_cmd.aligned_size()*idx; buf_desc[0].offset = ife_cmd.aligned_size()*idx;
// stream of IFE register writes // stream of IFE register writes
bool is_raw = output_type != ISP_IFE_PROCESSED;
if (!is_raw) { if (!is_raw) {
if (init) { if (init) {
buf_desc[0].length = build_initial_config((unsigned char*)ife_cmd.ptr + buf_desc[0].offset, sensor.get(), patches, cc.camera_num); buf_desc[0].length = build_initial_config((unsigned char*)ife_cmd.ptr + buf_desc[0].offset, sensor.get(), patches, cc.camera_num);
@ -597,8 +599,7 @@ void SpectraCamera::config_ife(int idx, int request_id, bool init) {
pkt->io_configs_offset = sizeof(struct cam_cmd_buf_desc)*pkt->num_cmd_buf; pkt->io_configs_offset = sizeof(struct cam_cmd_buf_desc)*pkt->num_cmd_buf;
struct cam_buf_io_cfg *io_cfg = (struct cam_buf_io_cfg *)((char*)&pkt->payload + pkt->io_configs_offset); struct cam_buf_io_cfg *io_cfg = (struct cam_buf_io_cfg *)((char*)&pkt->payload + pkt->io_configs_offset);
if (output_type != ISP_IFE_PROCESSED) {
if (is_raw) {
io_cfg[0].mem_handle[0] = buf_handle_raw[idx]; io_cfg[0].mem_handle[0] = buf_handle_raw[idx];
io_cfg[0].planes[0] = (struct cam_plane_cfg){ io_cfg[0].planes[0] = (struct cam_plane_cfg){
.width = sensor->frame_width, .width = sensor->frame_width,
@ -679,6 +680,8 @@ void SpectraCamera::enqueue_buffer(int i, bool dp) {
if (sync_objs[i]) { if (sync_objs[i]) {
// SOF has come in, wait until readout is complete // SOF has come in, wait until readout is complete
struct cam_sync_wait sync_wait = {0}; struct cam_sync_wait sync_wait = {0};
// wait for ife
sync_wait.sync_obj = sync_objs[i]; sync_wait.sync_obj = sync_objs[i];
// TODO: write a test to stress test w/ a low timeout and check camera frame ids match // TODO: write a test to stress test w/ a low timeout and check camera frame ids match
sync_wait.timeout_ms = 100; sync_wait.timeout_ms = 100;
@ -687,6 +690,18 @@ void SpectraCamera::enqueue_buffer(int i, bool dp) {
clear_req_queue(); clear_req_queue();
LOGE("failed to wait for sync: %d %d", ret, sync_wait.sync_obj); LOGE("failed to wait for sync: %d %d", ret, sync_wait.sync_obj);
} }
if (ret == 0 && output_type == ISP_BPS_PROCESSED) {
// wait for bps
sync_wait.sync_obj = sync_objs_bps_out[i];
sync_wait.timeout_ms = 50; // max dt tolerance, typical should be 23
ret = do_sync_control(m->cam_sync_fd, CAM_SYNC_WAIT, &sync_wait, sizeof(sync_wait));
if (ret != 0) {
clear_req_queue();
LOGE("failed to wait for sync: %d %d", ret, sync_wait.sync_obj);
}
}
buf.frame_metadata[i].timestamp_end_of_isp = (uint64_t)nanos_since_boot(); buf.frame_metadata[i].timestamp_end_of_isp = (uint64_t)nanos_since_boot();
buf.frame_metadata[i].timestamp_eof = buf.frame_metadata[i].timestamp_sof + sensor->readout_time_ns; buf.frame_metadata[i].timestamp_eof = buf.frame_metadata[i].timestamp_sof + sensor->readout_time_ns;
if (dp && ret == 0) { if (dp && ret == 0) {
@ -728,7 +743,7 @@ void SpectraCamera::enqueue_buffer(int i, bool dp) {
// submit request to IFE and BPS // submit request to IFE and BPS
config_ife(i, request_id); config_ife(i, request_id);
config_bps(i, request_id); if (output_type == ISP_BPS_PROCESSED) config_bps(i, request_id);
} }
void SpectraCamera::destroySyncObjectAt(int index) { void SpectraCamera::destroySyncObjectAt(int index) {
@ -751,7 +766,7 @@ void SpectraCamera::destroySyncObjectAt(int index) {
void SpectraCamera::camera_map_bufs() { void SpectraCamera::camera_map_bufs() {
int ret; int ret;
for (int i = 0; i < ife_buf_depth; i++) { for (int i = 0; i < ife_buf_depth; i++) {
// configure ISP to put the image in place // map our VisionIPC bufs into ISP memory
struct cam_mem_mgr_map_cmd mem_mgr_map_cmd = {0}; struct cam_mem_mgr_map_cmd mem_mgr_map_cmd = {0};
mem_mgr_map_cmd.flags = CAM_MEM_FLAG_HW_READ_WRITE; mem_mgr_map_cmd.flags = CAM_MEM_FLAG_HW_READ_WRITE;
mem_mgr_map_cmd.mmu_hdls[0] = m->device_iommu; mem_mgr_map_cmd.mmu_hdls[0] = m->device_iommu;
@ -761,14 +776,16 @@ void SpectraCamera::camera_map_bufs() {
mem_mgr_map_cmd.mmu_hdls[1] = m->icp_device_iommu; mem_mgr_map_cmd.mmu_hdls[1] = m->icp_device_iommu;
} }
if (is_raw) { if (output_type != ISP_IFE_PROCESSED) {
// RAW bayer images // RAW bayer images
mem_mgr_map_cmd.fd = buf.camera_bufs_raw[i].fd; mem_mgr_map_cmd.fd = buf.camera_bufs_raw[i].fd;
ret = do_cam_control(m->video0_fd, CAM_REQ_MGR_MAP_BUF, &mem_mgr_map_cmd, sizeof(mem_mgr_map_cmd)); ret = do_cam_control(m->video0_fd, CAM_REQ_MGR_MAP_BUF, &mem_mgr_map_cmd, sizeof(mem_mgr_map_cmd));
assert(ret == 0); assert(ret == 0);
LOGD("map buf req: (fd: %d) 0x%x %d", buf.camera_bufs_raw[i].fd, mem_mgr_map_cmd.out.buf_handle, ret); LOGD("map buf req: (fd: %d) 0x%x %d", buf.camera_bufs_raw[i].fd, mem_mgr_map_cmd.out.buf_handle, ret);
buf_handle_raw[i] = mem_mgr_map_cmd.out.buf_handle; buf_handle_raw[i] = mem_mgr_map_cmd.out.buf_handle;
} else { }
if (output_type != ISP_RAW_OUTPUT) {
// final processed images // final processed images
VisionBuf *vb = buf.vipc_server->get_buffer(buf.stream_type, i); VisionBuf *vb = buf.vipc_server->get_buffer(buf.stream_type, i);
mem_mgr_map_cmd.fd = vb->fd; mem_mgr_map_cmd.fd = vb->fd;
@ -865,7 +882,7 @@ void SpectraCamera::configISP() {
}, },
}; };
if (is_raw) { if (output_type != ISP_IFE_PROCESSED) {
in_port_info.line_start = 0; in_port_info.line_start = 0;
in_port_info.line_stop = sensor->frame_height + sensor->extra_height - 1; in_port_info.line_stop = sensor->frame_height + sensor->extra_height - 1;
in_port_info.height = sensor->frame_height + sensor->extra_height; in_port_info.height = sensor->frame_height + sensor->extra_height;
@ -890,7 +907,7 @@ void SpectraCamera::configISP() {
ife_cmd.init(m, 67984, 0x20, ife_cmd.init(m, 67984, 0x20,
CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE, CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE,
m->device_iommu, m->cdm_iommu, ife_buf_depth); m->device_iommu, m->cdm_iommu, ife_buf_depth);
if (!is_raw) { if (output_type == ISP_IFE_PROCESSED) {
assert(sensor->gamma_lut_rgb.size() == 64); assert(sensor->gamma_lut_rgb.size() == 64);
ife_gamma_lut.init(m, sensor->gamma_lut_rgb.size()*sizeof(uint32_t), 0x20, ife_gamma_lut.init(m, sensor->gamma_lut_rgb.size()*sizeof(uint32_t), 0x20,
CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE, CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE,
@ -1028,9 +1045,15 @@ void SpectraCamera::linkDevices() {
ret = device_control(csiphy_fd, CAM_START_DEV, session_handle, csiphy_dev_handle); ret = device_control(csiphy_fd, CAM_START_DEV, session_handle, csiphy_dev_handle);
LOGD("start csiphy: %d", ret); LOGD("start csiphy: %d", ret);
assert(ret == 0);
ret = device_control(m->isp_fd, CAM_START_DEV, session_handle, isp_dev_handle); ret = device_control(m->isp_fd, CAM_START_DEV, session_handle, isp_dev_handle);
LOGD("start isp: %d", ret); LOGD("start isp: %d", ret);
assert(ret == 0); assert(ret == 0);
if (output_type == ISP_BPS_PROCESSED) {
ret = device_control(m->icp_fd, CAM_START_DEV, session_handle, icp_dev_handle);
LOGD("start icp: %d", ret);
assert(ret == 0);
}
} }
void SpectraCamera::camera_close() { void SpectraCamera::camera_close() {
@ -1041,8 +1064,13 @@ void SpectraCamera::camera_close() {
// LOGD("stop sensor: %d", ret); // LOGD("stop sensor: %d", ret);
int ret = device_control(m->isp_fd, CAM_STOP_DEV, session_handle, isp_dev_handle); int ret = device_control(m->isp_fd, CAM_STOP_DEV, session_handle, isp_dev_handle);
LOGD("stop isp: %d", ret); LOGD("stop isp: %d", ret);
if (output_type == ISP_BPS_PROCESSED) {
ret = device_control(m->icp_fd, CAM_STOP_DEV, session_handle, icp_dev_handle);
LOGD("stop icp: %d", ret);
}
ret = device_control(csiphy_fd, CAM_STOP_DEV, session_handle, csiphy_dev_handle); ret = device_control(csiphy_fd, CAM_STOP_DEV, session_handle, csiphy_dev_handle);
LOGD("stop csiphy: %d", ret); LOGD("stop csiphy: %d", ret);
// link control stop // link control stop
LOG("-- Stop link control"); LOG("-- Stop link control");
struct cam_req_mgr_link_control req_mgr_link_control = {0}; struct cam_req_mgr_link_control req_mgr_link_control = {0};
@ -1069,11 +1097,20 @@ void SpectraCamera::camera_close() {
} }
ret = device_control(m->isp_fd, CAM_RELEASE_DEV, session_handle, isp_dev_handle); ret = device_control(m->isp_fd, CAM_RELEASE_DEV, session_handle, isp_dev_handle);
LOGD("release isp: %d", ret); LOGD("release isp: %d", ret);
if (output_type == ISP_BPS_PROCESSED) {
ret = device_control(m->icp_fd, CAM_RELEASE_DEV, session_handle, icp_dev_handle);
LOGD("release icp: %d", ret);
}
ret = device_control(csiphy_fd, CAM_RELEASE_DEV, session_handle, csiphy_dev_handle); ret = device_control(csiphy_fd, CAM_RELEASE_DEV, session_handle, csiphy_dev_handle);
LOGD("release csiphy: %d", ret); LOGD("release csiphy: %d", ret);
for (int i = 0; i < ife_buf_depth; i++) { for (int i = 0; i < ife_buf_depth; i++) {
release(m->video0_fd, is_raw ? buf_handle_raw[i] : buf_handle_yuv[i]); if (buf_handle_raw[i]) {
release(m->video0_fd, buf_handle_raw[i]);
}
if (buf_handle_yuv[i]) {
release(m->video0_fd, buf_handle_yuv[i]);
}
} }
LOGD("released buffers"); LOGD("released buffers");
} }

@ -29,6 +29,12 @@ const int MIPI_SETTLE_CNT = 33; // Calculated by camera_freqs.py
#define OpcodesIFEInitialConfig 0x0 #define OpcodesIFEInitialConfig 0x0
#define OpcodesIFEUpdate 0x1 #define OpcodesIFEUpdate 0x1
typedef enum {
ISP_RAW_OUTPUT, // raw frame from sensor
ISP_IFE_PROCESSED, // fully processed image through the IFE
ISP_BPS_PROCESSED, // fully processed image through the BPS
} SpectraOutputType;
std::optional<int32_t> device_acquire(int fd, int32_t session_handle, void *data, uint32_t num_resources=1); std::optional<int32_t> device_acquire(int fd, int32_t session_handle, void *data, uint32_t num_resources=1);
int device_config(int fd, int32_t session_handle, int32_t dev_handle, uint64_t packet_handle); int device_config(int fd, int32_t session_handle, int32_t dev_handle, uint64_t packet_handle);
int device_control(int fd, int op_code, int session_handle, int dev_handle); int device_control(int fd, int op_code, int session_handle, int dev_handle);
@ -103,7 +109,7 @@ public:
class SpectraCamera { class SpectraCamera {
public: public:
SpectraCamera(SpectraMaster *master, const CameraConfig &config, bool raw); SpectraCamera(SpectraMaster *master, const CameraConfig &config, SpectraOutputType out);
~SpectraCamera(); ~SpectraCamera();
void camera_open(VisionIpcServer *v, cl_device_id device_id, cl_context ctx); void camera_open(VisionIpcServer *v, cl_device_id device_id, cl_context ctx);
@ -177,7 +183,7 @@ public:
uint64_t idx_offset = 0; uint64_t idx_offset = 0;
bool skipped = true; bool skipped = true;
bool is_raw; SpectraOutputType output_type;
CameraBuf buf; CameraBuf buf;
MemoryManager mm; MemoryManager mm;

@ -5,7 +5,7 @@ set -e
# no CCI and UTIL, very spammy # no CCI and UTIL, very spammy
echo 0xfffdbfff | sudo tee /sys/module/cam_debug_util/parameters/debug_mdl echo 0xfffdbfff | sudo tee /sys/module/cam_debug_util/parameters/debug_mdl
echo 0 | sudo tee /sys/module/cam_debug_util/parameters/debug_mdl #echo 0 | sudo tee /sys/module/cam_debug_util/parameters/debug_mdl
sudo dmesg -C sudo dmesg -C
scons -u -j8 --minimal . scons -u -j8 --minimal .

Loading…
Cancel
Save