Make imx462 not green

Use the isp in the rockpi to apply white balance gains to the image.

Signed-off-by: Ravago Jones <ravagojones@gmail.com>
Change-Id: I4a9b3bedf6da952fc6519aa7ed24514bcfc21a5e
diff --git a/y2023/vision/camera_reader.cc b/y2023/vision/camera_reader.cc
index fca5d53..a69caf3 100644
--- a/y2023/vision/camera_reader.cc
+++ b/y2023/vision/camera_reader.cc
@@ -1,3 +1,6 @@
+#include <linux/videodev2.h>
+#include <sys/ioctl.h>
+
 #include "absl/strings/str_cat.h"
 #include "absl/strings/str_split.h"
 #include "aos/events/shm_event_loop.h"
@@ -5,9 +8,14 @@
 #include "aos/realtime.h"
 #include "frc971/vision/media_device.h"
 #include "frc971/vision/v4l2_reader.h"
+#include "y2023/vision/rkisp1-config.h"
 
 DEFINE_string(config, "aos_config.json", "Path to the config file to use.");
-DEFINE_bool(lowlight_camera, false, "Switch to use imx462 image sensor.");
+DEFINE_bool(lowlight_camera, true, "Switch to use imx462 image sensor.");
+
+DEFINE_double(red, 1.252, "Red gain");
+DEFINE_double(green, 1, "Green gain");
+DEFINE_double(blue, 1.96, "Blue gain");
 
 namespace y2023 {
 namespace vision {
@@ -96,12 +104,75 @@
   if (FLAGS_lowlight_camera) {
     v4l2_reader.SetGainExt(100);
     v4l2_reader.SetVerticalBlanking(1000);
-    v4l2_reader.SetExposure(50);
+    v4l2_reader.SetExposure(150);
   } else {
     v4l2_reader.SetGainExt(1000);
     v4l2_reader.SetExposure(1000);
   }
 
+  {
+    Entity *rkisp1_params = media_device->FindEntity("rkisp1_params");
+
+    LOG(INFO) << "Opening " << rkisp1_params->device();
+    aos::ScopedFD fd(open(rkisp1_params->device().c_str(), O_RDWR));
+    PCHECK(fd >= 0);
+
+    struct v4l2_capability capability;
+    memset(&capability, 0, sizeof(capability));
+    PCHECK(ioctl(fd.get(), VIDIOC_QUERYCAP, &capability) == 0);
+    CHECK(capability.device_caps & V4L2_CAP_META_OUTPUT);
+
+    // V4L2_META_FMT_RK_ISP1_PARAMS
+    // RK1P
+    uint32_t meta_params_format = (uint32_t)('R') | ((uint32_t)('K') << 8) |
+                                  ((uint32_t)('1') << 16) |
+                                  ((uint32_t)('P') << 24);
+    struct v4l2_format format;
+    std::memset(&format, 0, sizeof(format));
+    format.type = V4L2_BUF_TYPE_META_OUTPUT;
+
+    PCHECK(ioctl(fd.get(), VIDIOC_G_FMT, &format) == 0);
+    CHECK_EQ(format.fmt.meta.buffersize, 3048ul);
+    CHECK_EQ(format.fmt.meta.dataformat, meta_params_format);
+
+    struct v4l2_requestbuffers request;
+    memset(&request, 0, sizeof(request));
+    request.count = 1;
+    request.type = V4L2_BUF_TYPE_META_OUTPUT;
+    request.memory = V4L2_MEMORY_USERPTR;
+    PCHECK(ioctl(fd.get(), VIDIOC_REQBUFS, &request) == 0);
+
+    struct rkisp1_params_cfg configuration;
+    memset(&configuration, 0, sizeof(configuration));
+
+    configuration.module_cfg_update |= RKISP1_CIF_ISP_MODULE_AWB_GAIN;
+
+    configuration.others.awb_gain_config.gain_red = 256 * FLAGS_red;
+    configuration.others.awb_gain_config.gain_green_r = 256 * FLAGS_green;
+    configuration.others.awb_gain_config.gain_blue = 256 * FLAGS_blue;
+    configuration.others.awb_gain_config.gain_green_b = 256 * FLAGS_green;
+
+    // Enable the AWB gains
+    configuration.module_en_update |= RKISP1_CIF_ISP_MODULE_AWB_GAIN;
+    configuration.module_ens |= RKISP1_CIF_ISP_MODULE_AWB_GAIN;
+
+    struct v4l2_buffer buffer;
+    memset(&buffer, 0, sizeof(buffer));
+    buffer.memory = V4L2_MEMORY_USERPTR;
+    buffer.index = 0;
+    buffer.type = V4L2_BUF_TYPE_META_OUTPUT;
+    buffer.m.userptr = reinterpret_cast<uintptr_t>(&configuration);
+    buffer.length = format.fmt.meta.buffersize;
+
+    int type = V4L2_BUF_TYPE_META_OUTPUT;
+    PCHECK(ioctl(fd.get(), VIDIOC_STREAMON, &type) == 0);
+
+    PCHECK(ioctl(fd.get(), VIDIOC_QBUF, &buffer) == 0);
+    CHECK(buffer.flags & V4L2_BUF_FLAG_QUEUED);
+
+    PCHECK(ioctl(fd.get(), VIDIOC_DQBUF, &buffer) == 0);
+  }
+
   event_loop.Run();
 }