diff --git a/system/camerad/cameras/camera_common.cc b/system/camerad/cameras/camera_common.cc index 9fa9bb6a737329..2357bfd16860c1 100644 --- a/system/camerad/cameras/camera_common.cc +++ b/system/camerad/cameras/camera_common.cc @@ -7,7 +7,6 @@ #include "common/clutil.h" #include "common/swaglog.h" -#include "third_party/linux/include/msm_media_info.h" #include "system/camerad/cameras/spectra.h" @@ -65,13 +64,12 @@ void CameraBuf::init(cl_device_id device_id, cl_context context, SpectraCamera * const SensorInfo *sensor = cam->sensor.get(); - // RAW frame - const int frame_size = (sensor->frame_height + sensor->extra_height) * sensor->frame_stride; + // camera frame camera_bufs = std::make_unique(frame_buf_count); camera_bufs_metadata = std::make_unique(frame_buf_count); for (int i = 0; i < frame_buf_count; i++) { - camera_bufs[i].allocate(frame_size); + camera_bufs[i].allocate(cam->yuv_size); camera_bufs[i].init_cl(device_id, context); } LOGD("allocated %d CL buffers", frame_buf_count); @@ -79,20 +77,14 @@ void CameraBuf::init(cl_device_id device_id, cl_context context, SpectraCamera * out_img_width = sensor->frame_width; out_img_height = sensor->hdr_offset > 0 ? (sensor->frame_height - sensor->hdr_offset) / 2 : sensor->frame_height; - int nv12_width = VENUS_Y_STRIDE(COLOR_FMT_NV12, out_img_width); - int nv12_height = VENUS_Y_SCANLINES(COLOR_FMT_NV12, out_img_height); - assert(nv12_width == VENUS_UV_STRIDE(COLOR_FMT_NV12, out_img_width)); - assert(nv12_height/2 == VENUS_UV_SCANLINES(COLOR_FMT_NV12, out_img_height)); - size_t nv12_uv_offset = nv12_width * nv12_height; - // the encoder HW tells us the size it wants after setting it up. // TODO: VENUS_BUFFER_SIZE should give the size, but it's too small. dependent on encoder settings? - size_t nv12_size = (out_img_width <= 1344 ? 2900 : 2346)*nv12_width; + size_t nv12_size = (out_img_width <= 1344 ? 2900 : 2346)*cam->stride; - vipc_server->create_buffers_with_sizes(stream_type, YUV_BUFFER_COUNT, out_img_width, out_img_height, nv12_size, nv12_width, nv12_uv_offset); - LOGD("created %d YUV vipc buffers with size %dx%d", YUV_BUFFER_COUNT, nv12_width, nv12_height); + vipc_server->create_buffers_with_sizes(stream_type, YUV_BUFFER_COUNT, out_img_width, out_img_height, nv12_size, cam->stride, cam->uv_offset); + LOGD("created %d YUV vipc buffers with size %dx%d", YUV_BUFFER_COUNT, cam->stride, cam->y_height); - imgproc = new ImgProc(device_id, context, this, sensor, cam->cc.camera_num, nv12_width, nv12_uv_offset); + imgproc = new ImgProc(device_id, context, this, sensor, cam->cc.camera_num, cam->stride, cam->uv_offset); } CameraBuf::~CameraBuf() { @@ -115,7 +107,8 @@ bool CameraBuf::acquire(int expo_time) { cur_camera_buf = &camera_bufs[cur_buf_idx]; double start_time = millis_since_boot(); - imgproc->runKernel(camera_bufs[cur_buf_idx].buf_cl, cur_yuv_buf->buf_cl, out_img_width, out_img_height, expo_time); + //imgproc->runKernel(camera_bufs[cur_buf_idx].buf_cl, cur_yuv_buf->buf_cl, out_img_width, out_img_height, expo_time); + memcpy(cur_yuv_buf->addr, cur_camera_buf->addr, cur_camera_buf->len); cur_frame_data.processing_time = (millis_since_boot() - start_time) / 1000.0; VisionIpcBufExtra extra = { diff --git a/system/camerad/cameras/camera_qcom2.cc b/system/camerad/cameras/camera_qcom2.cc index df884e7b92340a..2fcf8bc8c30e40 100644 --- a/system/camerad/cameras/camera_qcom2.cc +++ b/system/camerad/cameras/camera_qcom2.cc @@ -320,7 +320,7 @@ void camerad_thread() { } for (auto &cam : cams) { - if (event_data->session_hdl == cam->camera.session_handle) { + if (cam->camera.enabled && event_data->session_hdl == cam->camera.session_handle) { cam->camera.handle_camera_event(event_data); break; } diff --git a/system/camerad/cameras/ife.h b/system/camerad/cameras/ife.h new file mode 100644 index 00000000000000..06e9be2a71344a --- /dev/null +++ b/system/camerad/cameras/ife.h @@ -0,0 +1,813 @@ +#include "cdm.h" + +#include +#include +#include +#include + + +void hexdump(uint8_t *data, int len) { + for (int i = 0; i < len; i++) { if (i!=0&&i%0x10==0) printf("\n"); printf("%02X ", data[i]); } printf("\n"); + for (int i = 0; i < len; i++) printf("\\x%02X", data[i]); + printf("\n"); +} + +int write_cont(uint8_t *dst, uint32_t reg, std::vector vals) { + struct cdm_regcontinuous_cmd *cmd = (struct cdm_regcontinuous_cmd*)dst; + cmd->cmd = CAM_CDM_CMD_REG_CONT; + cmd->count = vals.size(); + cmd->offset = reg; + cmd->reserved0 = 0; + cmd->reserved1 = 0; + + uint32_t *vd = (uint32_t*)(dst + sizeof(struct cdm_regcontinuous_cmd)); + for (int i = 0; i < vals.size(); i++) { + *vd = vals[i]; + vd++; + } + + return sizeof(struct cdm_regcontinuous_cmd) + vals.size()*sizeof(uint32_t); +} + +int write_random(uint8_t *dst, std::vector vals) { + struct cdm_regrandom_cmd *cmd = (struct cdm_regrandom_cmd*)dst; + cmd->cmd = CAM_CDM_CMD_REG_RANDOM; + cmd->count = vals.size() / 2; + cmd->reserved = 0; + + uint32_t *vd = (uint32_t*)(dst + sizeof(struct cdm_regrandom_cmd)); + for (int i = 0; i < vals.size(); i++) { + *vd = vals[i]; + vd++; + } + + return sizeof(struct cdm_regrandom_cmd) + vals.size()*sizeof(uint32_t); +} + +int build_initial_config(uint8_t *dst) { + uint8_t *start = dst; + + // constants, some kind of HW quirk? + dst += write_random(dst, { + 0x2c, 0xffffffff, + 0x30, 0xffffffff, + 0x34, 0xffffffff, + 0x38, 0xffffffff, + 0x3c, 0xffffffff, + }); + + dst += write_cont(dst, 0x478, { + 0x00000004, + 0x004000c0, + }); + + dst += write_cont(dst, 0x488, { + 0x00000000, + 0x00000000, + 0x00000f0f, + }); + + dst += write_cont(dst, 0x49c, { + 0x00000001, + }); + + dst += write_cont(dst, 0xce4, { + 0x00000000, + 0x00000000, + }); + + dst += write_cont(dst, 0x4dc, { + 0x00000000, + 0x04050b84, + 0x13031a82, + 0x22022981, + 0x3100387f, + 0x04010b80, + 0x13001a80, + 0x2200297f, + 0x30ff387f, + 0x04050b84, + 0x13031a82, + 0x22022981, + 0x3100387f, + 0x04010b80, + 0x13001a80, + 0x2200297f, + 0x30ff387f, + 0x04050b84, + 0x13031a82, + 0x22022981, + 0x3100387f, + 0x04010b80, + 0x13001a80, + 0x2200297f, + 0x30ff387f, + 0x04050b84, + 0x13031a82, + 0x22022981, + 0x3100387f, + 0x04010b80, + 0x13001a80, + 0x2200297f, + 0x30ff387f, + }); + /* TODO + cdm_dmi_cmd_t 248 + .length = 287 + .reserved = 33 + .cmd = 11 + .addr = 0 + .DMIAddr = 3108 + .DMISel = 9 + */ + + dst += write_cont(dst, 0x560, { + 0x00000001, + 0x04440444, + 0x04450445, + 0x04440444, + 0x04450445, + 0x000000ca, + 0x0000009c, + }); + + dst += write_cont(dst, 0x5e8, { + 0x06363005, + }); + + dst += write_cont(dst, 0x5f4, { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x3b3839a0, + 0x003f8040, + 0x00000000, + 0x00000000, + 0x00078000, + 0x00078000, + 0x00078000, + 0x00078000, + 0x00078000, + 0x00078000, + 0x00078000, + 0x00078000, + 0x00000009, + 0x00400808, + 0x00000044, + 0x004000a0, + 0x0a0d00a6, + 0x0a0d00a6, + }); + /* TODO + cdm_dmi_cmd_t 392 + .length = 255 + .reserved = 33 + .cmd = 10 + .addr = 0 + .DMIAddr = 3108 + .DMISel = 12 + */ + + dst += write_cont(dst, 0x6bc, { + 0x0b3c0000, + 0x00670067, + 0xd3b1300c, + 0x13b1300c, + 0x00670067, + 0xd3b1300c, + 0x13b1300c, + 0xec4e4000, + 0x0100c003, + 0xec4e4000, + 0x0100c003, + }); + /* TODO + cdm_dmi_cmd_t 444 + .length = 883 + .reserved = 33 + .cmd = 10 + .addr = 0 + .DMIAddr = 3108 + .DMISel = 14 + */ + /* TODO + cdm_dmi_cmd_t 444 + .length = 883 + .reserved = 33 + .cmd = 10 + .addr = 0 + .DMIAddr = 3108 + .DMISel = 15 + */ + + dst += write_cont(dst, 0x6fc, { + 0x00bf0080, + 0x00000106, + 0x00000000, + 0x00000000, + }); + + dst += write_cont(dst, 0x6f8, { + 0x00000100, + }); + + dst += write_cont(dst, 0x71c, { + 0x00008000, + 0x08000066, + }); + + dst += write_cont(dst, 0x760, { + 0x00800080, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00800080, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00800080, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + }); + + dst += write_cont(dst, 0x794, { + 0x00000000, + }); + /* TODO + cdm_dmi_cmd_t 568 + .length = 511 + .reserved = 33 + .cmd = 11 + .addr = 0 + .DMIAddr = 3108 + .DMISel = 24 + */ + + dst += write_cont(dst, 0x798, { + 0x00000000, + }); + /* TODO + cdm_dmi_cmd_t 580 + .length = 255 + .reserved = 33 + .cmd = 10 + .addr = 0 + .DMIAddr = 3108 + .DMISel = 26 + */ + /* TODO + cdm_dmi_cmd_t 580 + .length = 255 + .reserved = 33 + .cmd = 10 + .addr = 0 + .DMIAddr = 3108 + .DMISel = 28 + */ + /* TODO + cdm_dmi_cmd_t 580 + .length = 255 + .reserved = 33 + .cmd = 10 + .addr = 0 + .DMIAddr = 3108 + .DMISel = 30 + */ + + dst += write_cont(dst, 0xf30, { + 0x00750259, + 0x00000132, + 0x00000000, + 0x03ff0000, + 0x01fe1eae, + 0x00001f54, + 0x02000000, + 0x03ff0000, + 0x1fad1e55, + 0x000001fe, + 0x02000000, + 0x03ff0000, + }); + + dst += write_cont(dst, 0xa3c, { + 0x00000003, + 0x07870787, + 0x30036666, + 0x00000000, + 0x00000000, + 0x00000787, + 0x04b704b7, + 0x30036666, + 0x00000000, + 0x00000000, + 0x000004b7, + }); + + dst += write_cont(dst, 0xa68, { + 0x00000003, + 0x03c30787, + 0x3006cccc, + 0x00000000, + 0x00000000, + 0x00000787, + 0x025b04b7, + 0x3006cccc, + 0x00000000, + 0x00000000, + 0x00000787, + }); + + + dst += write_cont(dst, 0xe10, { + 0x000004b7, + 0x00000787, + }); + + dst += write_cont(dst, 0xe30, { + 0x0000025b, + 0x00000787, + }); + + dst += write_cont(dst, 0xe18, { + 0x0ff00000, + 0x00000016, + }); + + dst += write_cont(dst, 0xe38, { + 0x0ff00000, + 0x00000017, + }); + + dst += write_cont(dst, 0xd84, { + 0x000004b7, + 0x00000787, + }); + + dst += write_cont(dst, 0xda4, { + 0x000004b7, + 0x00000787, + }); + + dst += write_cont(dst, 0xd60, { + 0x04380300, + 0x09016c7d, + 0x021c0300, + }); + + dst += write_cont(dst, 0xd98, { + 0x0ff00000, + 0x00000016, + }); + + dst += write_cont(dst, 0xdb8, { + 0x0ff00000, + 0x00000017, + }); + + dst += write_cont(dst, 0xd6c, { + 0x00000300, + }); + + dst += write_cont(dst, 0xd70, { + 0x010e0f00, + 0x09016c7d, + 0x00870f00, + }); + + dst += write_cont(dst, 0xd7c, { + 0x00000f00, + }); + + dst += write_cont(dst, 0x40, { + 0x00000586, + }); + + dst += write_cont(dst, 0x48, { + 0x0000000e, + }); + + dst += write_cont(dst, 0x4c, { + 0x00000019, + }); + + dst += write_cont(dst, 0xe4c, { + 0x00000000, + }); + + dst += write_cont(dst, 0xe6c, { + 0x00000000, + }); + + dst += write_cont(dst, 0xe0c, { + 0x00000e00, + }); + + dst += write_cont(dst, 0xe2c, { + 0x00000e00, + }); + + dst += write_cont(dst, 0xd8c, { + 0x00000000, + }); + + dst += write_cont(dst, 0xdac, { + 0x00000000, + }); + + dst += write_cont(dst, 0xdcc, { + 0x00000000, + }); + + dst += write_cont(dst, 0xdec, { + 0x00000000, + }); + + dst += write_cont(dst, 0x44, { + 0x00000000, + }); + + dst += write_cont(dst, 0xaac, { + 0x00000040, + }); + + dst += write_cont(dst, 0xf00, { + 0x00000000, + }); + + //hexdump(start, dst - start); + return dst - start; +} + +int build_first_update(uint8_t *dst) { + uint8_t *start = dst; + + dst += write_random(dst, { + 0x2c, 0xffffffff, + 0x30, 0xffffffff, + 0x34, 0xffffffff, + 0x38, 0xffffffff, + 0x3c, 0xffffffff, + }); + + dst += write_cont(dst, 0x4dc, { + 0x00000001, + 0x04050b84, + 0x13031a82, + 0x22022981, + 0x3100387f, + 0x04010b80, + 0x13001a80, + 0x2200297f, + 0x30ff387f, + 0x04050b84, + 0x13031a82, + 0x22022981, + 0x3100387f, + 0x04010b80, + 0x13001a80, + 0x2200297f, + 0x30ff387f, + 0x04050b84, + 0x13031a82, + 0x22022981, + 0x3100387f, + 0x04010b80, + 0x13001a80, + 0x2200297f, + 0x30ff387f, + 0x04050b84, + 0x13031a82, + 0x22022981, + 0x3100387f, + 0x04010b80, + 0x13001a80, + 0x2200297f, + 0x30ff387f, + }); + /* TODO + cdm_dmi_cmd_t 184 + .length = 287 + .reserved = 33 + .cmd = 11 + .addr = 832 + .DMIAddr = 3108 + .DMISel = 10 + */ + + dst += write_cont(dst, 0x560, { + 0x00000001, + 0x04440444, + 0x04450445, + 0x04440444, + 0x04450445, + 0x000000ca, + 0x0000009c, + }); + + dst += write_cont(dst, 0x5c4, { + 0x00000000, + 0x00001000, + 0x00001000, + 0x00001000, + 0x00001000, + 0x00800080, + 0x00802040, + 0x00000000, + }); + + dst += write_cont(dst, 0x5e8, { + 0x06363007, + }); + + dst += write_cont(dst, 0x5f4, { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x3b3839a0, + 0x003f8040, + 0x00000000, + 0x00000000, + 0x00078000, + 0x00078000, + 0x00078000, + 0x00078000, + 0x00078000, + 0x00078000, + 0x00078000, + 0x00078000, + 0x00000009, + 0x00400808, + 0x00000044, + 0x004000a0, + 0x0a0d00a6, + 0x0a0d00a6, + }); + /* TODO + cdm_dmi_cmd_t 368 + .length = 255 + .reserved = 33 + .cmd = 10 + .addr = 5344 + .DMIAddr = 3108 + .DMISel = 13 + */ + + dst += write_cont(dst, 0x6fc, { + 0x00800080, + 0x00000080, + 0x00000000, + 0x00000000, + }); + + dst += write_cont(dst, 0x6f8, { + 0x00000100, + }); + + dst += write_cont(dst, 0x71c, { + 0x00008000, + 0x08000066, + }); + + dst += write_cont(dst, 0x794, { + 0x00000001, + }); + /* TODO + cdm_dmi_cmd_t 432 + .length = 511 + .reserved = 33 + .cmd = 11 + .addr = 832 + .DMIAddr = 3108 + .DMISel = 25 + */ + + dst += write_cont(dst, 0x798, { + 0x00000007, + }); + /* TODO + cdm_dmi_cmd_t 444 + .length = 255 + .reserved = 33 + .cmd = 10 + .addr = 5344 + .DMIAddr = 3108 + .DMISel = 27 + */ + /* TODO + cdm_dmi_cmd_t 444 + .length = 255 + .reserved = 33 + .cmd = 10 + .addr = 5344 + .DMIAddr = 3108 + .DMISel = 29 + */ + /* TODO + cdm_dmi_cmd_t 444 + .length = 255 + .reserved = 33 + .cmd = 10 + .addr = 5344 + .DMIAddr = 3108 + .DMISel = 31 + */ + + dst += write_cont(dst, 0xd84, { + 0x000004b7, + 0x00000787, + }); + + dst += write_cont(dst, 0xda4, { + 0x000004b7, + 0x00000787, + }); + + dst += write_cont(dst, 0xd6c, { + 0x00000300, + }); + + dst += write_cont(dst, 0xd70, { + 0x02640f00, + 0x09016c7d, + 0x01320f00, + }); + + dst += write_cont(dst, 0xd7c, { + 0x00000f00, + }); + + dst += write_cont(dst, 0x40, { + 0x00000444, + }); + + dst += write_cont(dst, 0x48, { + 0x00000000, + }); + + dst += write_cont(dst, 0x4c, { + 0x00000019, + }); + + dst += write_cont(dst, 0xe4c, { + 0x00000000, + }); + + dst += write_cont(dst, 0xe6c, { + 0x00000000, + }); + + dst += write_cont(dst, 0xe0c, { + 0x00000e00, + }); + + dst += write_cont(dst, 0xe2c, { + 0x00000e00, + }); + + dst += write_cont(dst, 0xd8c, { + 0x00000000, + }); + + dst += write_cont(dst, 0xdac, { + 0x00000000, + }); + + dst += write_cont(dst, 0xdcc, { + 0x00000000, + }); + + dst += write_cont(dst, 0xdec, { + 0x00000000, + }); + + dst += write_cont(dst, 0x44, { + 0x00000000, + }); + + dst += write_cont(dst, 0xaac, { + 0x00000040, + }); + + dst += write_cont(dst, 0xf00, { + 0x00000000, + }); + + //printf("\n***** wrote out %ld bytes, togo %ld\n", dst - start, 1100 - (dst-start)); + return dst - start; +} + +int build_update(uint8_t *dst) { + uint8_t *start = dst; + + dst += write_random(dst, { + 0x2c, 0xffffffff, + 0x30, 0xffffffff, + 0x34, 0xffffffff, + 0x38, 0xffffffff, + 0x3c, 0xffffffff, + }); + + dst += write_cont(dst, 0x560, { + 0x00000001, + 0x04440444, + 0x04450445, + 0x04440444, + 0x04450445, + 0x000000ca, + 0x0000009c, + }); + + dst += write_cont(dst, 0x6fc, { + 0x00800080, + 0x00000080, + 0x00000000, + 0x00000000, + }); + + dst += write_cont(dst, 0xd84, { + 0x000004b7, + 0x00000787, + }); + + dst += write_cont(dst, 0xda4, { + 0x000004b7, + 0x00000787, + }); + + dst += write_cont(dst, 0xd6c, { + 0x00000300, + }); + + dst += write_cont(dst, 0xd70, { + 0x02640f00, + 0x09016c7d, + 0x01320f00, + }); + + dst += write_cont(dst, 0xd7c, { + 0x00000f00, + }); + + dst += write_cont(dst, 0x40, { + 0x00000444, + }); + + dst += write_cont(dst, 0x48, { + 0x00000000, + }); + + dst += write_cont(dst, 0x4c, { + 0x00000019, + }); + + dst += write_cont(dst, 0xe4c, { + 0x00000000, + }); + + dst += write_cont(dst, 0xe6c, { + 0x00000000, + }); + + dst += write_cont(dst, 0xe0c, { + 0x00000e00, + }); + + dst += write_cont(dst, 0xe2c, { + 0x00000e00, + }); + + dst += write_cont(dst, 0xd8c, { + 0x00000000, + }); + + dst += write_cont(dst, 0xdac, { + 0x00000000, + }); + + dst += write_cont(dst, 0xdcc, { + 0x00000000, + }); + + dst += write_cont(dst, 0xdec, { + 0x00000000, + }); + + dst += write_cont(dst, 0x44, { + 0x00000000, + }); + + dst += write_cont(dst, 0xaac, { + 0x00000040, + }); + + dst += write_cont(dst, 0xf00, { + 0x00000000, + }); + + //printf("\n***** wrote out %ld bytes, togo %ld\n", dst - start, 1100 - (dst-start)); + return dst - start; +} diff --git a/system/camerad/cameras/spectra.cc b/system/camerad/cameras/spectra.cc index ef771a64b72467..8c9c14c112b037 100644 --- a/system/camerad/cameras/spectra.cc +++ b/system/camerad/cameras/spectra.cc @@ -11,7 +11,9 @@ #include "common/util.h" #include "common/swaglog.h" +#include "system/camerad/cameras/ife.h" #include "system/camerad/cameras/spectra.h" +#include "third_party/linux/include/msm_media_info.h" // For debugging: // echo "4294967295" > /sys/module/cam_debug_util/parameters/debug_mdl @@ -225,6 +227,15 @@ void SpectraCamera::camera_open(VisionIpcServer *v, cl_device_id device_id, cl_c return; } + // size is driven by all the HW that, the encoder has certain alignment requirements in this case + stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, sensor->frame_width); + y_height = VENUS_Y_SCANLINES(COLOR_FMT_NV12, sensor->frame_height); + uv_height = VENUS_UV_SCANLINES(COLOR_FMT_NV12, sensor->frame_height); + uv_offset = ALIGNED_SIZE(stride*y_height, 0x1000); + yuv_size = uv_offset + ALIGNED_SIZE(stride*uv_height, 0x1000); + assert(stride == VENUS_UV_STRIDE(COLOR_FMT_NV12, sensor->frame_width)); + assert(y_height/2 == uv_height); + open = true; configISP(); configCSIPHY(); @@ -394,9 +405,11 @@ int SpectraCamera::sensors_init() { void SpectraCamera::config_ife(int io_mem_handle, int fence, int request_id, int buf0_idx) { /* Handles initial + per-frame IFE config. - IFE = Image Front End + * IFE = Image Front End + * see camxifenode.cpp in camx */ int size = sizeof(struct cam_packet) + sizeof(struct cam_cmd_buf_desc)*2; + //size += sizeof(struct cam_patch_desc)*(request_id > 1 ? 0x2 : 0x8); if (io_mem_handle != 0) { size += sizeof(struct cam_buf_io_cfg); } @@ -413,12 +426,6 @@ void SpectraCamera::config_ife(int io_mem_handle, int fence, int request_id, int } pkt->header.size = size; - // *** kmd cmd buf *** - { - pkt->kmd_cmd_buf_index = 0; - pkt->kmd_cmd_buf_offset = 0; - } - // *** cmd buf *** { struct cam_cmd_buf_desc *buf_desc = (struct cam_cmd_buf_desc *)&pkt->payload; @@ -427,12 +434,22 @@ void SpectraCamera::config_ife(int io_mem_handle, int fence, int request_id, int // *** first command *** // TODO: support MMU buf_desc[0].size = buf0_size; - buf_desc[0].length = 0; buf_desc[0].type = CAM_CMD_BUF_DIRECT; - buf_desc[0].meta_data = 3; + buf_desc[0].meta_data = CAM_ISP_PACKET_META_COMMON; buf_desc[0].mem_handle = buf0_handle; buf_desc[0].offset = ALIGNED_SIZE(buf0_size, buf0_alignment)*buf0_idx; + // this is a stream of IFE register configs and DMI commands + if (io_mem_handle == 0) { + buf_desc[0].length = build_initial_config((unsigned char*)buf0_ptr + buf_desc[0].offset); + } else if (request_id == 1) { + buf_desc[0].length = build_first_update((unsigned char*)buf0_ptr + buf_desc[0].offset); + } else { + buf_desc[0].length = build_update((unsigned char*)buf0_ptr + buf_desc[0].offset); + } + pkt->kmd_cmd_buf_offset = buf_desc[0].length; + pkt->kmd_cmd_buf_index = 0; + // *** second command *** // parsed by cam_isp_packet_generic_blob_handler struct isp_packet { @@ -453,9 +470,9 @@ void SpectraCamera::config_ife(int io_mem_handle, int fence, int request_id, int tmp.type_0 |= sizeof(cam_isp_resource_hfr_config) << 8; static_assert(sizeof(cam_isp_resource_hfr_config) == 0x20); tmp.resource_hfr = { - .num_ports = 1, // 10 for YUV (but I don't think we need them) + .num_ports = 1, .port_hfr_config[0] = { - .resource_type = CAM_ISP_IFE_OUT_RES_RDI_0, // CAM_ISP_IFE_OUT_RES_FULL for YUV + .resource_type = CAM_ISP_IFE_OUT_RES_FULL, .subsample_pattern = 1, .subsample_period = 0, .framedrop_pattern = 1, @@ -466,7 +483,7 @@ void SpectraCamera::config_ife(int io_mem_handle, int fence, int request_id, int tmp.type_1 |= (sizeof(cam_isp_clock_config) + sizeof(tmp.extra_rdi_hz)) << 8; static_assert((sizeof(cam_isp_clock_config) + sizeof(tmp.extra_rdi_hz)) == 0x38); tmp.clock = { - .usage_type = 1, // dual mode + .usage_type = 0, // dual mode .num_rdi = 4, .left_pix_hz = 404000000, .right_pix_hz = 404000000, @@ -477,17 +494,22 @@ void SpectraCamera::config_ife(int io_mem_handle, int fence, int request_id, int tmp.type_2 |= (sizeof(cam_isp_bw_config) + sizeof(tmp.extra_rdi_vote)) << 8; static_assert((sizeof(cam_isp_bw_config) + sizeof(tmp.extra_rdi_vote)) == 0xe0); tmp.bw = { - .usage_type = 1, // dual mode + .usage_type = 0, // dual mode .num_rdi = 4, .left_pix_vote = { .resource_id = 0, - .cam_bw_bps = 450000000, - .ext_bw_bps = 450000000, + .cam_bw_bps = 0x59db2c80, + .ext_bw_bps = 0x59db2c80, + }, + .right_pix_vote = { + .resource_id = 0, + .cam_bw_bps = 0x59db2c80, + .ext_bw_bps = 0x59db2c80, }, .rdi_vote[0] = { .resource_id = 0, - .cam_bw_bps = 8706200000, - .ext_bw_bps = 8706200000, + .cam_bw_bps = 0, + .ext_bw_bps = 0, }, }; @@ -509,30 +531,27 @@ void SpectraCamera::config_ife(int io_mem_handle, int fence, int request_id, int 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); - io_cfg[0].offsets[0] = 0; io_cfg[0].mem_handle[0] = io_mem_handle; + io_cfg[0].mem_handle[1] = io_mem_handle; io_cfg[0].planes[0] = (struct cam_plane_cfg){ .width = sensor->frame_width, - .height = sensor->frame_height + sensor->extra_height, - .plane_stride = sensor->frame_stride, - .slice_height = sensor->frame_height + sensor->extra_height, - - // these are for UBWC, we'll want that eventually - .meta_stride = 0x0, - .meta_size = 0x0, - .meta_offset = 0x0, - .packer_config = 0x0, - .mode_config = 0x0, - .tile_config = 0x0, - .h_init = 0x0, - .v_init = 0x0, + .height = sensor->frame_height, + .plane_stride = stride, + .slice_height = y_height, }; - io_cfg[0].format = sensor->mipi_format; // CAM_FORMAT_UBWC_TP10 for YUV - io_cfg[0].color_space = CAM_COLOR_SPACE_BASE; // CAM_COLOR_SPACE_BT601_FULL for YUV - io_cfg[0].color_pattern = 0x5; // 0x0 for YUV - io_cfg[0].bpp = (sensor->mipi_format == CAM_FORMAT_MIPI_RAW_10 ? 0xa : 0xc); // bits per pixel - io_cfg[0].resource_type = CAM_ISP_IFE_OUT_RES_RDI_0; // CAM_ISP_IFE_OUT_RES_FULL for YUV + io_cfg[0].planes[1] = (struct cam_plane_cfg){ + .width = sensor->frame_width, + .height = sensor->frame_height/2, + .plane_stride = stride, + .slice_height = uv_height, + }; + io_cfg[0].offsets[1] = uv_offset; + io_cfg[0].format = CAM_FORMAT_NV12; // TODO: why is this NV21 here and NV12 in the initial device acquire? + io_cfg[0].color_space = 0; + io_cfg[0].color_pattern = 0x0; + io_cfg[0].bpp = 0; + io_cfg[0].resource_type = CAM_ISP_IFE_OUT_RES_FULL; io_cfg[0].fence = fence; io_cfg[0].direction = CAM_BUF_OUTPUT; io_cfg[0].subsample_pattern = 0x1; @@ -540,6 +559,7 @@ void SpectraCamera::config_ife(int io_mem_handle, int fence, int request_id, int } // *** patches *** + // sets up the kernel driver to do address translation for the IFE { pkt->num_patches = 0; pkt->patch_offset = sizeof(struct cam_cmd_buf_desc)*pkt->num_cmd_buf + sizeof(struct cam_buf_io_cfg)*pkt->num_io_configs; @@ -671,7 +691,7 @@ void SpectraCamera::configISP() { .dt = sensor->frame_data_type, .format = sensor->mipi_format, - .test_pattern = 0x2, // 0x3? + .test_pattern = CAM_ISP_PATTERN_BAYER_GRGRGR, .usage_type = 0x0, .left_start = 0, @@ -695,8 +715,8 @@ void SpectraCamera::configISP() { // ISP outputs .num_out_res = 0x1, .data[0] = (struct cam_isp_out_port_info){ - .res_type = CAM_ISP_IFE_OUT_RES_RDI_0, - .format = sensor->mipi_format, + .res_type = CAM_ISP_IFE_OUT_RES_FULL, + .format = CAM_FORMAT_NV12, .width = sensor->frame_width, .height = sensor->frame_height + sensor->extra_height, .comp_grp_id = 0x0, .split_point = 0x0, .secure_mode = 0x0, @@ -715,9 +735,10 @@ void SpectraCamera::configISP() { LOGD("acquire isp dev"); // config IFE - alloc_w_mmu_hdl(m->video0_fd, FRAME_BUF_COUNT*ALIGNED_SIZE(buf0_size, buf0_alignment), (uint32_t*)&buf0_handle, buf0_alignment, - 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); + buf0_ptr = alloc_w_mmu_hdl(m->video0_fd, FRAME_BUF_COUNT*ALIGNED_SIZE(buf0_size, buf0_alignment), (uint32_t*)&buf0_handle, buf0_alignment, + 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); + config_ife(0, 0, 1, 0); } diff --git a/system/camerad/cameras/spectra.h b/system/camerad/cameras/spectra.h index 5796f47098f47e..0a5868c615decf 100644 --- a/system/camerad/cameras/spectra.h +++ b/system/camerad/cameras/spectra.h @@ -99,6 +99,13 @@ class SpectraCamera { CameraConfig cc; std::unique_ptr sensor; + // YUV image size + uint32_t stride; + uint32_t y_height; + uint32_t uv_height; + uint32_t uv_offset; + uint32_t yuv_size; + unique_fd sensor_fd; unique_fd csiphy_fd; @@ -109,10 +116,12 @@ class SpectraCamera { int32_t link_handle = -1; - const int buf0_size = 65624; // unclear what this is and how it's determined, for internal ISP use? it's just copied from an ioctl dump + // IFE command buffer + void *buf0_ptr; + int buf0_handle = 0; + const int buf0_size = 67984; // unclear what this is and how it's determined, for internal ISP use? it's just copied from an ioctl dump const int buf0_alignment = 0x20; - int buf0_handle = 0; int buf_handle[FRAME_BUF_COUNT] = {}; int sync_objs[FRAME_BUF_COUNT] = {}; uint64_t request_ids[FRAME_BUF_COUNT] = {}; diff --git a/system/camerad/test/intercept.sh b/system/camerad/test/intercept.sh new file mode 100755 index 00000000000000..e269929afc5feb --- /dev/null +++ b/system/camerad/test/intercept.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +DISABLE_ROAD=1 DISABLE_WIDE_ROAD=1 DEBUG_FRAMES=1 LOGPRINT=debug LD_PRELOAD=/data/tici_test_scripts/isp/interceptor/tmpioctl.so ./camerad