From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Andrey Skvortsov <andrej.skvortzov@gmail.com>
Date: Sat, 26 Aug 2023 12:10:49 +0300
Subject: media: gc2145: fix white-balance colors

awb initialization settings were taken from gc2145.c driver developed
by STMicroelectronics with a help of Galaxycore. Most of these
registers are not documented in a publicly available gc2145
documentation.

Don't reset white balance gains, exposure and gains on every stream
start. That keeps old values set by AWB/AEC previously and makes
AWB/AEC algorithms achieve correct settings on stream restart faster.

For Megapixels DCP calibration file for front camera has to be removed
to get good quality pictures.
```
rm /usr/share/megapixels/config/pine64,pinephone,front.dcp
```

Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
---
 drivers/media/i2c/gc2145.c | 118 ++++++++--
 1 file changed, 97 insertions(+), 21 deletions(-)

diff --git a/drivers/media/i2c/gc2145.c b/drivers/media/i2c/gc2145.c
index d5d97e07c38e..507734b9de7d 100644
--- a/drivers/media/i2c/gc2145.c
+++ b/drivers/media/i2c/gc2145.c
@@ -1,6 +1,7 @@
 /*
  * Galaxycore GC2145 driver.
  * Copyright (C) 2018 Ondřej Jirman <megi@xff.cz>.
+ * Copyright (C) 2022, STMicroelectronics SA
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -1615,34 +1616,114 @@ static int gc2145_set_2pclk(struct gc2145_dev *sensor,
 	return gc2145_tx_commit(sensor);
 }
 
+struct gc2145_reg {
+	unsigned char address;
+	unsigned char val;
+};
+
+static const struct gc2145_reg gc2145_awb_regs[] = {
+	{0xfe, 0x01},
+	{0x4f, 0x00}, {0x4f, 0x00}, {0x4b, 0x01}, {0x4f, 0x00},
+	{0x4c, 0x01}, {0x4d, 0x71}, {0x4e, 0x01},
+	{0x4c, 0x01}, {0x4d, 0x91}, {0x4e, 0x01},
+	{0x4c, 0x01}, {0x4d, 0x70}, {0x4e, 0x01},
+	{0x4c, 0x01}, {0x4d, 0x90}, {0x4e, 0x02},
+	{0x4c, 0x01}, {0x4d, 0xb0}, {0x4e, 0x02},
+	{0x4c, 0x01}, {0x4d, 0x8f}, {0x4e, 0x02},
+	{0x4c, 0x01}, {0x4d, 0x6f}, {0x4e, 0x02},
+	{0x4c, 0x01}, {0x4d, 0xaf}, {0x4e, 0x02},
+	{0x4c, 0x01}, {0x4d, 0xd0}, {0x4e, 0x02},
+	{0x4c, 0x01}, {0x4d, 0xf0}, {0x4e, 0x02},
+	{0x4c, 0x01}, {0x4d, 0xcf}, {0x4e, 0x02},
+	{0x4c, 0x01}, {0x4d, 0xef}, {0x4e, 0x02},
+	{0x4c, 0x01}, {0x4d, 0x6e}, {0x4e, 0x03},
+	{0x4c, 0x01}, {0x4d, 0x8e}, {0x4e, 0x03},
+	{0x4c, 0x01}, {0x4d, 0xae}, {0x4e, 0x03},
+	{0x4c, 0x01}, {0x4d, 0xce}, {0x4e, 0x03},
+	{0x4c, 0x01}, {0x4d, 0x4d}, {0x4e, 0x03},
+	{0x4c, 0x01}, {0x4d, 0x6d}, {0x4e, 0x03},
+	{0x4c, 0x01}, {0x4d, 0x8d}, {0x4e, 0x03},
+	{0x4c, 0x01}, {0x4d, 0xad}, {0x4e, 0x03},
+	{0x4c, 0x01}, {0x4d, 0xcd}, {0x4e, 0x03},
+	{0x4c, 0x01}, {0x4d, 0x4c}, {0x4e, 0x03},
+	{0x4c, 0x01}, {0x4d, 0x6c}, {0x4e, 0x03},
+	{0x4c, 0x01}, {0x4d, 0x8c}, {0x4e, 0x03},
+	{0x4c, 0x01}, {0x4d, 0xac}, {0x4e, 0x03},
+	{0x4c, 0x01}, {0x4d, 0xcc}, {0x4e, 0x03},
+	{0x4c, 0x01}, {0x4d, 0xcb}, {0x4e, 0x03},
+	{0x4c, 0x01}, {0x4d, 0x4b}, {0x4e, 0x03},
+	{0x4c, 0x01}, {0x4d, 0x6b}, {0x4e, 0x03},
+	{0x4c, 0x01}, {0x4d, 0x8b}, {0x4e, 0x03},
+	{0x4c, 0x01}, {0x4d, 0xab}, {0x4e, 0x03},
+	{0x4c, 0x01}, {0x4d, 0x8a}, {0x4e, 0x04},
+	{0x4c, 0x01}, {0x4d, 0xaa}, {0x4e, 0x04},
+	{0x4c, 0x01}, {0x4d, 0xca}, {0x4e, 0x04},
+	{0x4c, 0x01}, {0x4d, 0xca}, {0x4e, 0x04},
+	{0x4c, 0x01}, {0x4d, 0xc9}, {0x4e, 0x04},
+	{0x4c, 0x01}, {0x4d, 0x8a}, {0x4e, 0x04},
+	{0x4c, 0x01}, {0x4d, 0x89}, {0x4e, 0x04},
+	{0x4c, 0x01}, {0x4d, 0xa9}, {0x4e, 0x04},
+	{0x4c, 0x02}, {0x4d, 0x0b}, {0x4e, 0x05},
+	{0x4c, 0x02}, {0x4d, 0x0a}, {0x4e, 0x05},
+	{0x4c, 0x01}, {0x4d, 0xeb}, {0x4e, 0x05},
+	{0x4c, 0x01}, {0x4d, 0xea}, {0x4e, 0x05},
+	{0x4c, 0x02}, {0x4d, 0x09}, {0x4e, 0x05},
+	{0x4c, 0x02}, {0x4d, 0x29}, {0x4e, 0x05},
+	{0x4c, 0x02}, {0x4d, 0x2a}, {0x4e, 0x05},
+	{0x4c, 0x02}, {0x4d, 0x4a}, {0x4e, 0x05},
+	{0x4c, 0x02}, {0x4d, 0x8a}, {0x4e, 0x06},
+	{0x4c, 0x02}, {0x4d, 0x49}, {0x4e, 0x06},
+	{0x4c, 0x02}, {0x4d, 0x69}, {0x4e, 0x06},
+	{0x4c, 0x02}, {0x4d, 0x89}, {0x4e, 0x06},
+	{0x4c, 0x02}, {0x4d, 0xa9}, {0x4e, 0x06},
+	{0x4c, 0x02}, {0x4d, 0x48}, {0x4e, 0x06},
+	{0x4c, 0x02}, {0x4d, 0x68}, {0x4e, 0x06},
+	{0x4c, 0x02}, {0x4d, 0x69}, {0x4e, 0x06},
+	{0x4c, 0x02}, {0x4d, 0xca}, {0x4e, 0x07},
+	{0x4c, 0x02}, {0x4d, 0xc9}, {0x4e, 0x07},
+	{0x4c, 0x02}, {0x4d, 0xe9}, {0x4e, 0x07},
+	{0x4c, 0x03}, {0x4d, 0x09}, {0x4e, 0x07},
+	{0x4c, 0x02}, {0x4d, 0xc8}, {0x4e, 0x07},
+	{0x4c, 0x02}, {0x4d, 0xe8}, {0x4e, 0x07},
+	{0x4c, 0x02}, {0x4d, 0xa7}, {0x4e, 0x07},
+	{0x4c, 0x02}, {0x4d, 0xc7}, {0x4e, 0x07},
+	{0x4c, 0x02}, {0x4d, 0xe7}, {0x4e, 0x07},
+	{0x4c, 0x03}, {0x4d, 0x07}, {0x4e, 0x07},
+	{0x4f, 0x01},
+	{0x50, 0x80}, {0x51, 0xa8}, {0x52, 0x47}, {0x53, 0x38},
+	{0x54, 0xc7}, {0x56, 0x0e}, {0x58, 0x08}, {0x5b, 0x00},
+	{0x5c, 0x74}, {0x5d, 0x8b}, {0x61, 0xdb}, {0x62, 0xb8},
+	{0x63, 0x86}, {0x64, 0xc0}, {0x65, 0x04}, {0x67, 0xa8},
+	{0x68, 0xb0}, {0x69, 0x00}, {0x6a, 0xa8}, {0x6b, 0xb0},
+	{0x6c, 0xaf}, {0x6d, 0x8b}, {0x6e, 0x50}, {0x6f, 0x18},
+	{0x73, 0xf0}, {0x70, 0x0d}, {0x71, 0x60}, {0x72, 0x80},
+	{0x74, 0x01}, {0x75, 0x01}, {0x7f, 0x0c}, {0x76, 0x70},
+	{0x77, 0x58}, {0x78, 0xa0}, {0x79, 0x5e}, {0x7a, 0x54},
+	{0x7b, 0x58},
+	{0xfe, 0x00},
+};
+
 static int gc2145_setup_awb(struct gc2145_dev *sensor,
 			     u16 x1, u16 y1, u16 x2, u16 y2)
 {
 	int ratio = 8; //XXX: manual for gc2035 FAE says 4
 
-	gc2145_tx_start(sensor);
-
 	// disable awb
-	gc2145_tx_update_bits(sensor, 0x82, BIT(1), 0);
+	gc2145_update_bits(sensor, 0x82, BIT(1), 0);
 
-	// reset white balance RGB gains
-	gc2145_tx_write8(sensor, 0xb3, 0x40);
-	gc2145_tx_write8(sensor, 0xb4, 0x40);
-	gc2145_tx_write8(sensor, 0xb5, 0x40);
+	// load awb settings
+	gc2145_set_registers(sensor, (void*)gc2145_awb_regs, sizeof(gc2145_awb_regs));
 
 	// awb window
-	gc2145_tx_write8(sensor, 0x1ec, x1 / ratio);
-	gc2145_tx_write8(sensor, 0x1ed, y1 / ratio);
-	gc2145_tx_write8(sensor, 0x1ee, x2 / ratio);
-	gc2145_tx_write8(sensor, 0x1ef, y2 / ratio);
+	gc2145_write(sensor, 0x1ec, x1 / ratio);
+	gc2145_write(sensor, 0x1ed, y1 / ratio);
+	gc2145_write(sensor, 0x1ee, x2 / ratio);
+	gc2145_write(sensor, 0x1ef, y2 / ratio);
 
 	// eanble awb
-	gc2145_tx_update_bits(sensor, 0x82, BIT(1), BIT(1));
-
-	//1051  { 0xfe, 0x01 },
-	//1052  { 0x74, 0x01 },
+	gc2145_update_bits(sensor, 0x82, BIT(1), BIT(1));
 
-	return gc2145_tx_commit(sensor);
+	return 0;
 }
 
 static int gc2145_setup_aec(struct gc2145_dev *sensor,
@@ -1658,11 +1739,6 @@ static int gc2145_setup_aec(struct gc2145_dev *sensor,
 	// disable AEC
 	gc2145_tx_write8(sensor, 0xb6, 0);
 
-	// set reasonable initial exposure and gains
-	gc2145_tx_write16(sensor, 0x03, 1200);
-	gc2145_tx_write8(sensor, 0xb1, 0x20);
-	gc2145_tx_write8(sensor, 0xb2, 0xe0);
-
 	// setup measure window
 	gc2145_tx_write8(sensor, 0x101, x1 / x_ratio);
 	gc2145_tx_write8(sensor, 0x102, x2 / x_ratio);
-- 
Armbian

