From 9a9318148f3bb9ea17760867c48da601fcf5b333 Mon Sep 17 00:00:00 2001
From: hmz007 <hmz007@gmail.com>
Date: Fri, 10 May 2024 14:27:42 +0800
Subject: [PATCH] [kernel] merge commit 'e59373e15c..24337da3a9'

Signed-off-by: hmz007 <hmz007@gmail.com>
---
 .../dts/rockchip/rk3568-nanopi5-common.dtsi   |  26 +-
 .../dts/rockchip/rk3568-nanopi5-rev02.dts     |   5 +
 .../dts/rockchip/rk3588-nanopi6-common.dtsi   |  22 +
 .../dts/rockchip/rk3588-nanopi6-rev01.dts     |  19 +-
 .../dts/rockchip/rk3588-nanopi6-rev08.dts     |  13 +
 .../dts/rockchip/rk3588-nanopi6-rev09.dts     |  20 +-
 kernel-5.10/drivers/hwmon/pwm-fan.c           | 546 +++++++++++++-----
 kernel-5.10/drivers/media/usb/uvc/Kconfig     |  11 +
 .../drivers/media/usb/uvc/uvc_driver.c        | 327 +++++++++++
 kernel-5.10/drivers/media/usb/uvc/uvcvideo.h  |  43 ++
 .../drivers/media/v4l2-core/v4l2-ioctl.c      |   9 +
 kernel-5.10/drivers/power/supply/Kconfig      |   8 +
 kernel-5.10/drivers/power/supply/Makefile     |   1 +
 .../drivers/power/supply/simple_adc_power.c   | 179 ++++++
 kernel-5.10/drivers/power/supply/test_power.c |   2 +-
 .../include/soc/rockchip/rockchip_dmc.h       |   2 +-
 kernel-5.10/include/uapi/linux/videodev2.h    |   9 +
 17 files changed, 1069 insertions(+), 173 deletions(-)
 create mode 100644 kernel-5.10/drivers/power/supply/simple_adc_power.c

diff --git a/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3568-nanopi5-common.dtsi b/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3568-nanopi5-common.dtsi
index 41cdf3bd6ce..ce91b0f632b 100644
--- a/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3568-nanopi5-common.dtsi
+++ b/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3568-nanopi5-common.dtsi
@@ -84,7 +84,7 @@
 		compatible = "simple-audio-card";
 		simple-audio-card,format = "i2s";
 		simple-audio-card,mclk-fs = <128>;
-		simple-audio-card,name = "rockchip,hdmi";
+		simple-audio-card,name = "rockchip,hdmi0";
 		status = "disabled";
 
 		simple-audio-card,cpu {
@@ -123,7 +123,7 @@
 	};
 
 	rk809_sound: rk809-sound {
-		status = "okay";
+		status = "disabled";
 		compatible = "simple-audio-card";
 		simple-audio-card,format = "i2s";
 		simple-audio-card,name = "rockchip,rk809-codec";
@@ -133,7 +133,7 @@
 			sound-dai = <&i2s1_8ch>;
 		};
 		simple-audio-card,codec {
-			sound-dai = <&rk809_codec 0>;
+			sound-dai = <&rk809_codec>;
 		};
 	};
 
@@ -229,6 +229,19 @@
 		pinctrl-0 = <&vcc5v0_otg_en>;
 	};
 
+	simple_bat: battery {
+		compatible = "simple-battery";
+		voltage-max-design-microvolt = <13000000>;
+		voltage-min-design-microvolt = <4500000>;
+	};
+
+	simple_vin: simple-vin {
+		compatible = "simple-adc-power-v1";
+		io-channels = <&saradc 2>;
+		io-channel-names = "voltage";
+		monitored-battery = <&simple_bat>;
+	};
+
 	test-power {
 		status = "okay";
 	};
@@ -562,7 +575,7 @@
 		};
 
 		rk809_codec: codec {
-			#sound-dai-cells = <1>;
+			#sound-dai-cells = <0>;
 			compatible = "rockchip,rk809-codec", "rockchip,rk817-codec";
 			clocks = <&cru I2S1_MCLKOUT>;
 			clock-names = "mclk";
@@ -573,7 +586,6 @@
 			pinctrl-0 = <&i2s1m0_mclk>;
 			hp-volume = <20>;
 			spk-volume = <3>;
-			mic-in-differential;
 			status = "okay";
 		};
 	};
@@ -592,7 +604,7 @@
 
 &i2s1_8ch {
 	status = "disabled";
-	rockchip,clk-trcm = <1>;
+	rockchip,trcm-sync-tx-only;
 	pinctrl-names = "default";
 	pinctrl-0 = <&i2s1m0_sclktx
 		     &i2s1m0_lrcktx
@@ -842,11 +854,11 @@
 };
 
 &u2phy0_otg {
+	phy-supply = <&vcc5v0_otg>;
 	status = "okay";
 };
 
 &u2phy1_host {
-	phy-supply = <&vcc5v0_otg>;
 	status = "okay";
 };
 
diff --git a/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3568-nanopi5-rev02.dts b/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3568-nanopi5-rev02.dts
index 6781337edcf..514cbc20b75 100644
--- a/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3568-nanopi5-rev02.dts
+++ b/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3568-nanopi5-rev02.dts
@@ -214,3 +214,8 @@
 &sfc {
 	status = "disabled";
 };
+
+&simple_bat {
+	voltage-max-design-microvolt = <5400000>;
+	voltage-min-design-microvolt = <4200000>;
+};
diff --git a/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588-nanopi6-common.dtsi b/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588-nanopi6-common.dtsi
index c3728f2e192..81e785c2e61 100644
--- a/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588-nanopi6-common.dtsi
+++ b/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588-nanopi6-common.dtsi
@@ -121,6 +121,19 @@
 		compatible = "pwm-backlight";
 	};
 
+	simple_bat: battery {
+		compatible = "simple-battery";
+		voltage-max-design-microvolt = <21000000>;
+		voltage-min-design-microvolt = <4500000>;
+	};
+
+	simple_vin: simple-vin {
+		compatible = "simple-adc-power-v2";
+		io-channels = <&saradc 2>;
+		io-channel-names = "voltage";
+		monitored-battery = <&simple_bat>;
+	};
+
 	test-power {
 		status = "okay";
 	};
@@ -157,6 +170,11 @@
 	mem-supply = <&vdd_cpu_big1_mem_s0>;
 };
 
+&display_subsystem {
+	clocks = <&hdptxphy_hdmi_clk0>, <&hdptxphy_hdmi_clk0>;
+	clock-names = "hdmi0_phy_pll", "hdmi1_phy_pll";
+};
+
 &gpu {
 	mali-supply = <&vdd_gpu_s0>;
 	mem-supply = <&vdd_gpu_mem_s0>;
@@ -215,6 +233,10 @@
 	status = "okay";
 };
 
+&hdptxphy_hdmi_clk0 {
+	status = "okay";
+};
+
 &hdptxphy_hdmi0 {
 	status = "okay";
 };
diff --git a/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev01.dts b/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev01.dts
index 457098ca207..f75f10a77d0 100644
--- a/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev01.dts
+++ b/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev01.dts
@@ -73,11 +73,13 @@
 	};
 
 	fan: pwm-fan {
-		status = "disabled";
+		status = "okay";
 		compatible = "pwm-fan";
 		#cooling-cells = <2>;
+		fan-supply = <&vcc5v0_sys>;
 		pwms = <&pwm1 0 50000 0>;
-		cooling-levels = <0 50 100 150 200 255>;
+		cooling-levels = <0 45 70 110 160 255>;
+		rockchip,hold-time-ms = <2000>;
 		rockchip,temp-trips = <
 			50000	1
 			55000	2
@@ -181,6 +183,11 @@
 	status = "okay";
 };
 
+&display_subsystem {
+	clocks = <&hdptxphy_hdmi_clk0>, <&hdptxphy_hdmi_clk1>;
+	clock-names = "hdmi0_phy_pll", "hdmi1_phy_pll";
+};
+
 &dp0 {
 	status = "okay";
 };
@@ -263,6 +270,14 @@
 	pinctrl-0 = <&hdmim1_rx &hdmirx_det>;
 };
 
+&hdptxphy_hdmi_clk0 {
+	status = "okay";
+};
+
+&hdptxphy_hdmi_clk1 {
+	status = "okay";
+};
+
 &hdptxphy_hdmi0 {
 	status = "okay";
 };
diff --git a/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev08.dts b/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev08.dts
index 456745883f8..324fdc7f21d 100644
--- a/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev08.dts
+++ b/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev08.dts
@@ -131,6 +131,11 @@
 	status = "okay";
 };
 
+&display_subsystem {
+	clocks = <&hdptxphy_hdmi_clk0>, <&hdptxphy_hdmi_clk1>;
+	clock-names = "hdmi0_phy_pll", "hdmi1_phy_pll";
+};
+
 &dp0 {
 	status = "okay";
 };
@@ -193,6 +198,14 @@
 	status = "okay";
 };
 
+&hdptxphy_hdmi_clk0 {
+	status = "okay";
+};
+
+&hdptxphy_hdmi_clk1 {
+	status = "okay";
+};
+
 &hdptxphy_hdmi0 {
 	status = "okay";
 };
diff --git a/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev09.dts b/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev09.dts
index e2fc7c4180e..ea0a9a80771 100644
--- a/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev09.dts
+++ b/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev09.dts
@@ -72,11 +72,13 @@
 	};
 
 	fan: pwm-fan {
-		status = "disabled";
+		status = "okay";
 		compatible = "pwm-fan";
 		#cooling-cells = <2>;
+		fan-supply = <&vcc5v0_sys>;
 		pwms = <&pwm1 0 50000 0>;
-		cooling-levels = <0 50 100 150 200 255>;
+		cooling-levels = <0 45 70 110 160 255>;
+		rockchip,hold-time-ms = <2000>;
 		rockchip,temp-trips = <
 			50000	1
 			55000	2
@@ -214,6 +216,11 @@
 	status = "okay";
 };
 
+&display_subsystem {
+	clocks = <&hdptxphy_hdmi_clk0>, <&hdptxphy_hdmi_clk1>;
+	clock-names = "hdmi0_phy_pll", "hdmi1_phy_pll";
+};
+
 &dp0 {
 	status = "okay";
 };
@@ -296,6 +303,14 @@
 	pinctrl-0 = <&hdmim1_rx &hdmirx_det>;
 };
 
+&hdptxphy_hdmi_clk0 {
+	status = "okay";
+};
+
+&hdptxphy_hdmi_clk1 {
+	status = "okay";
+};
+
 &hdptxphy_hdmi0 {
 	status = "okay";
 };
@@ -415,6 +430,7 @@
 };
 
 &i2c8 {
+	status = "okay";
 	pinctrl-0 = <&i2c8m2_xfer>;
 	/* connected with Header_2.54MM */
 };
diff --git a/kernel-5.10/drivers/hwmon/pwm-fan.c b/kernel-5.10/drivers/hwmon/pwm-fan.c
index 6298da53ef1..381be156102 100644
--- a/kernel-5.10/drivers/hwmon/pwm-fan.c
+++ b/kernel-5.10/drivers/hwmon/pwm-fan.c
@@ -8,7 +8,6 @@
  */
 
 #include <linux/hwmon.h>
-#include <linux/hwmon-sysfs.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
@@ -23,20 +22,38 @@
 
 #define MAX_PWM 255
 
+struct pwm_fan_tach {
+	int irq;
+	atomic_t pulses;
+	unsigned int rpm;
+	u8 pulses_per_revolution;
+};
+
+enum pwm_fan_enable_mode {
+	pwm_off_reg_off,
+	pwm_disable_reg_enable,
+	pwm_enable_reg_enable,
+	pwm_disable_reg_disable,
+};
+
 struct thermal_trips {
 	int temp;
 	int state;
 };
 
 struct pwm_fan_ctx {
+	struct device *dev;
+
 	struct mutex lock;
 	struct pwm_device *pwm;
+	struct pwm_state pwm_state;
 	struct regulator *reg_en;
+	enum pwm_fan_enable_mode enable_mode;
+	bool regulator_enabled;
+	bool enabled;
 
-	int irq;
-	atomic_t pulses;
-	unsigned int rpm;
-	u8 pulses_per_revolution;
+	int tach_count;
+	struct pwm_fan_tach *tachs;
 	ktime_t sample_start;
 	struct timer_list rpm_timer;
 
@@ -48,14 +65,19 @@ struct pwm_fan_ctx {
 	struct notifier_block thermal_nb;
 	struct thermal_trips *thermal_trips;
 	bool thermal_notifier_is_ok;
+	unsigned int delay_ms;
+	ktime_t time_in_state;
+
+	struct hwmon_chip_info info;
+	struct hwmon_channel_info fan_channel;
 };
 
 /* This handler assumes self resetting edge triggered interrupt. */
 static irqreturn_t pulse_handler(int irq, void *dev_id)
 {
-	struct pwm_fan_ctx *ctx = dev_id;
+	struct pwm_fan_tach *tach = dev_id;
 
-	atomic_inc(&ctx->pulses);
+	atomic_inc(&tach->pulses);
 
 	return IRQ_HANDLED;
 }
@@ -64,13 +86,18 @@ static void sample_timer(struct timer_list *t)
 {
 	struct pwm_fan_ctx *ctx = from_timer(ctx, t, rpm_timer);
 	unsigned int delta = ktime_ms_delta(ktime_get(), ctx->sample_start);
-	int pulses;
+	int i;
 
 	if (delta) {
-		pulses = atomic_read(&ctx->pulses);
-		atomic_sub(pulses, &ctx->pulses);
-		ctx->rpm = (unsigned int)(pulses * 1000 * 60) /
-			(ctx->pulses_per_revolution * delta);
+		for (i = 0; i < ctx->tach_count; i++) {
+			struct pwm_fan_tach *tach = &ctx->tachs[i];
+			int pulses;
+
+			pulses = atomic_read(&tach->pulses);
+			atomic_sub(pulses, &tach->pulses);
+			tach->rpm = (unsigned int)(pulses * 1000 * 60) /
+				(tach->pulses_per_revolution * delta);
+		}
 
 		ctx->sample_start = ktime_get();
 	}
@@ -78,26 +105,140 @@ static void sample_timer(struct timer_list *t)
 	mod_timer(&ctx->rpm_timer, jiffies + HZ);
 }
 
+static void pwm_fan_enable_mode_2_state(int enable_mode,
+					struct pwm_state *state,
+					bool *enable_regulator)
+{
+	switch (enable_mode) {
+	case pwm_disable_reg_enable:
+		/* disable pwm, keep regulator enabled */
+		state->enabled = false;
+		*enable_regulator = true;
+		break;
+	case pwm_enable_reg_enable:
+		/* keep pwm and regulator enabled */
+		state->enabled = true;
+		*enable_regulator = true;
+		break;
+	case pwm_off_reg_off:
+	case pwm_disable_reg_disable:
+		/* disable pwm and regulator */
+		state->enabled = false;
+		*enable_regulator = false;
+	}
+}
+
+static int pwm_fan_switch_power(struct pwm_fan_ctx *ctx, bool on)
+{
+	int ret = 0;
+
+	if (!ctx->reg_en)
+		return ret;
+
+	if (!ctx->regulator_enabled && on) {
+		ret = regulator_enable(ctx->reg_en);
+		if (ret == 0)
+			ctx->regulator_enabled = true;
+	} else if (ctx->regulator_enabled && !on) {
+		ret = regulator_disable(ctx->reg_en);
+		if (ret == 0)
+			ctx->regulator_enabled = false;
+	}
+	return ret;
+}
+
+static int pwm_fan_power_on(struct pwm_fan_ctx *ctx)
+{
+	struct pwm_state *state = &ctx->pwm_state;
+	int ret;
+
+	if (ctx->enabled)
+		return 0;
+
+	ret = pwm_fan_switch_power(ctx, true);
+	if (ret < 0) {
+		dev_err(ctx->dev, "failed to enable power supply\n");
+		return ret;
+	}
+
+	state->enabled = true;
+	ret = pwm_apply_state(ctx->pwm, state);
+	if (ret) {
+		dev_err(ctx->dev, "failed to enable PWM\n");
+		goto disable_regulator;
+	}
+
+	ctx->enabled = true;
+
+	return 0;
+
+disable_regulator:
+	pwm_fan_switch_power(ctx, false);
+	return ret;
+}
+
+static int pwm_fan_power_off(struct pwm_fan_ctx *ctx)
+{
+	struct pwm_state *state = &ctx->pwm_state;
+	bool enable_regulator = false;
+	int ret;
+
+	if (!ctx->enabled)
+		return 0;
+
+	pwm_fan_enable_mode_2_state(ctx->enable_mode,
+				    state,
+				    &enable_regulator);
+
+	state->enabled = false;
+	state->duty_cycle = 0;
+	ret = pwm_apply_state(ctx->pwm, state);
+	if (ret) {
+		dev_err(ctx->dev, "failed to disable PWM\n");
+		return ret;
+	}
+
+	pwm_fan_switch_power(ctx, enable_regulator);
+
+	ctx->enabled = false;
+
+	return 0;
+}
+
 static int  __set_pwm(struct pwm_fan_ctx *ctx, unsigned long pwm)
 {
+	struct pwm_state *state = &ctx->pwm_state;
 	unsigned long period;
 	int ret = 0;
-	struct pwm_state state = { };
 
-	mutex_lock(&ctx->lock);
-	if (ctx->pwm_value == pwm)
-		goto exit_set_pwm_err;
+	if (pwm > 0) {
+		if (ctx->enable_mode == pwm_off_reg_off)
+			/* pwm-fan hard disabled */
+			return 0;
 
-	pwm_init_state(ctx->pwm, &state);
-	period = ctx->pwm->args.period;
-	state.duty_cycle = DIV_ROUND_UP(pwm * (period - 1), MAX_PWM);
-	state.enabled = pwm ? true : false;
-
-	ret = pwm_apply_state(ctx->pwm, &state);
+		period = state->period;
+		state->duty_cycle = DIV_ROUND_UP(pwm * (period - 1), MAX_PWM);
+		ret = pwm_apply_state(ctx->pwm, state);
+		if (ret)
+			return ret;
+		ret = pwm_fan_power_on(ctx);
+	} else {
+		ret = pwm_fan_power_off(ctx);
+	}
 	if (!ret)
 		ctx->pwm_value = pwm;
-exit_set_pwm_err:
+
+	return ret;
+}
+
+static int set_pwm(struct pwm_fan_ctx *ctx, unsigned long pwm)
+{
+	int ret;
+
+	mutex_lock(&ctx->lock);
+	ret = __set_pwm(ctx, pwm);
 	mutex_unlock(&ctx->lock);
+
 	return ret;
 }
 
@@ -112,70 +253,127 @@ static void pwm_fan_update_state(struct pwm_fan_ctx *ctx, unsigned long pwm)
 	ctx->pwm_fan_state = i;
 }
 
-static ssize_t pwm_store(struct device *dev, struct device_attribute *attr,
-			 const char *buf, size_t count)
+static int pwm_fan_update_enable(struct pwm_fan_ctx *ctx, long val)
 {
-	struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
-	unsigned long pwm;
-	int ret;
+	int ret = 0;
+	int old_val;
 
-	if (kstrtoul(buf, 10, &pwm) || pwm > MAX_PWM)
-		return -EINVAL;
+	mutex_lock(&ctx->lock);
 
-	ret = __set_pwm(ctx, pwm);
-	if (ret)
-		return ret;
+	if (ctx->enable_mode == val)
+		goto out;
 
-	pwm_fan_update_state(ctx, pwm);
-	return count;
-}
+	old_val = ctx->enable_mode;
+	ctx->enable_mode = val;
 
-static ssize_t pwm_show(struct device *dev, struct device_attribute *attr,
-			char *buf)
-{
-	struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
+	if (val == 0) {
+		/* Disable pwm-fan unconditionally */
+		if (ctx->enabled)
+			ret = __set_pwm(ctx, 0);
+		else
+			ret = pwm_fan_switch_power(ctx, false);
+		if (ret)
+			ctx->enable_mode = old_val;
+		pwm_fan_update_state(ctx, 0);
+	} else {
+		/*
+		 * Change PWM and/or regulator state if currently disabled
+		 * Nothing to do if currently enabled
+		 */
+		if (!ctx->enabled) {
+			struct pwm_state *state = &ctx->pwm_state;
+			bool enable_regulator = false;
+
+			state->duty_cycle = 0;
+			pwm_fan_enable_mode_2_state(val,
+						    state,
+						    &enable_regulator);
+
+			pwm_apply_state(ctx->pwm, state);
+			pwm_fan_switch_power(ctx, enable_regulator);
+			pwm_fan_update_state(ctx, 0);
+		}
+	}
+out:
+	mutex_unlock(&ctx->lock);
 
-	return sprintf(buf, "%u\n", ctx->pwm_value);
+	return ret;
 }
 
-static ssize_t rpm_show(struct device *dev,
-			struct device_attribute *attr, char *buf)
+static int pwm_fan_write(struct device *dev, enum hwmon_sensor_types type,
+			 u32 attr, int channel, long val)
 {
 	struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
+	int ret;
 
-	return sprintf(buf, "%u\n", ctx->rpm);
-}
+	switch (attr) {
+	case hwmon_pwm_input:
+		if (val < 0 || val > MAX_PWM)
+			return -EINVAL;
+		ret = set_pwm(ctx, val);
+		if (ret)
+			return ret;
+		pwm_fan_update_state(ctx, val);
+		break;
+	case hwmon_pwm_enable:
+		if (val < 0 || val > 3)
+			ret = -EINVAL;
+		else
+			ret = pwm_fan_update_enable(ctx, val);
 
-static SENSOR_DEVICE_ATTR_RW(pwm1, pwm, 0);
-static SENSOR_DEVICE_ATTR_RO(fan1_input, rpm, 0);
+		return ret;
+	default:
+		return -EOPNOTSUPP;
+	}
 
-static struct attribute *pwm_fan_attrs[] = {
-	&sensor_dev_attr_pwm1.dev_attr.attr,
-	&sensor_dev_attr_fan1_input.dev_attr.attr,
-	NULL,
-};
+	return 0;
+}
 
-static umode_t pwm_fan_attrs_visible(struct kobject *kobj, struct attribute *a,
-				     int n)
+static int pwm_fan_read(struct device *dev, enum hwmon_sensor_types type,
+			u32 attr, int channel, long *val)
 {
-	struct device *dev = container_of(kobj, struct device, kobj);
 	struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
 
-	/* Hide fan_input in case no interrupt is available  */
-	if (n == 1 && ctx->irq <= 0)
+	switch (type) {
+	case hwmon_pwm:
+		switch (attr) {
+		case hwmon_pwm_input:
+			*val = ctx->pwm_value;
+			return 0;
+		case hwmon_pwm_enable:
+			*val = ctx->enable_mode;
+			return 0;
+		}
+		return -EOPNOTSUPP;
+	case hwmon_fan:
+		*val = ctx->tachs[channel].rpm;
 		return 0;
 
-	return a->mode;
+	default:
+		return -ENOTSUPP;
+	}
 }
 
-static const struct attribute_group pwm_fan_group = {
-	.attrs = pwm_fan_attrs,
-	.is_visible = pwm_fan_attrs_visible,
-};
+static umode_t pwm_fan_is_visible(const void *data,
+				  enum hwmon_sensor_types type,
+				  u32 attr, int channel)
+{
+	switch (type) {
+	case hwmon_pwm:
+		return 0644;
 
-static const struct attribute_group *pwm_fan_groups[] = {
-	&pwm_fan_group,
-	NULL,
+	case hwmon_fan:
+		return 0444;
+
+	default:
+		return 0;
+	}
+}
+
+static const struct hwmon_ops pwm_fan_hwmon_ops = {
+	.is_visible = pwm_fan_is_visible,
+	.read = pwm_fan_read,
+	.write = pwm_fan_write,
 };
 
 /* thermal cooling device callbacks */
@@ -214,10 +412,14 @@ pwm_fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
 	if (!ctx || (state > ctx->pwm_fan_max_state))
 		return -EINVAL;
 
+	/* keep running after user request */
+	if (ctx->delay_ms > 0)
+		ctx->time_in_state = ktime_add_ms(ktime_get(), ctx->delay_ms);
+
 	if (state == ctx->pwm_fan_state)
 		return 0;
 
-	ret = __set_pwm(ctx, ctx->pwm_fan_cooling_levels[state]);
+	ret = set_pwm(ctx, ctx->pwm_fan_cooling_levels[state]);
 	if (ret) {
 		dev_err(&cdev->device, "Cannot set pwm!\n");
 		return ret;
@@ -275,16 +477,14 @@ static int pwm_fan_of_get_cooling_data(struct device *dev,
 	return 0;
 }
 
-static void pwm_fan_regulator_disable(void *data)
-{
-	regulator_disable(data);
-}
-
-static void pwm_fan_pwm_disable(void *__ctx)
+static void pwm_fan_cleanup(void *__ctx)
 {
 	struct pwm_fan_ctx *ctx = __ctx;
-	pwm_disable(ctx->pwm);
+
 	del_timer_sync(&ctx->rpm_timer);
+	/* Switch off everything */
+	ctx->enable_mode = pwm_disable_reg_disable;
+	pwm_fan_power_off(ctx);
 }
 
 static int pwm_fan_get_thermal_trips(struct device *dev, char *porp_name,
@@ -354,7 +554,12 @@ static int pwm_fan_thermal_notifier_call(struct notifier_block *nb,
 	if (state == ctx->pwm_fan_state)
 		return NOTIFY_OK;
 
-	ret = __set_pwm(ctx, ctx->pwm_fan_cooling_levels[state]);
+	if (ktime_before(ktime_get(), ctx->time_in_state) &&
+	    state < ctx->pwm_fan_max_state) {
+		return NOTIFY_DONE;
+	}
+
+	ret = set_pwm(ctx, ctx->pwm_fan_cooling_levels[state]);
 	if (ret)
 		return NOTIFY_BAD;
 
@@ -382,8 +587,10 @@ static int pwm_fan_probe(struct platform_device *pdev)
 	struct pwm_fan_ctx *ctx;
 	struct device *hwmon;
 	int ret;
-	struct pwm_state state = { };
-	u32 ppr = 2;
+	const struct hwmon_channel_info **channels;
+	u32 *fan_channel_config;
+	int channel_count = 1;	/* We always have a PWM channel. */
+	int i;
 
 	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
 	if (!ctx)
@@ -391,81 +598,125 @@ static int pwm_fan_probe(struct platform_device *pdev)
 
 	mutex_init(&ctx->lock);
 
-	ctx->pwm = devm_of_pwm_get(dev, dev->of_node, NULL);
+	ctx->dev = &pdev->dev;
+	ctx->pwm = devm_pwm_get(dev, NULL);
 	if (IS_ERR(ctx->pwm))
 		return dev_err_probe(dev, PTR_ERR(ctx->pwm), "Could not get PWM\n");
 
 	platform_set_drvdata(pdev, ctx);
 
-	ctx->irq = platform_get_irq_optional(pdev, 0);
-	if (ctx->irq == -EPROBE_DEFER)
-		return ctx->irq;
-
 	ctx->reg_en = devm_regulator_get_optional(dev, "fan");
 	if (IS_ERR(ctx->reg_en)) {
 		if (PTR_ERR(ctx->reg_en) != -ENODEV)
 			return PTR_ERR(ctx->reg_en);
 
 		ctx->reg_en = NULL;
-	} else {
-		ret = regulator_enable(ctx->reg_en);
-		if (ret) {
-			dev_err(dev, "Failed to enable fan supply: %d\n", ret);
-			return ret;
-		}
-		ret = devm_add_action_or_reset(dev, pwm_fan_regulator_disable,
-					       ctx->reg_en);
-		if (ret)
-			return ret;
 	}
 
-	ctx->pwm_value = MAX_PWM;
+	pwm_init_state(ctx->pwm, &ctx->pwm_state);
 
-	pwm_init_state(ctx->pwm, &state);
 	/*
-	 * __set_pwm assumes that MAX_PWM * (period - 1) fits into an unsigned
+	 * set_pwm assumes that MAX_PWM * (period - 1) fits into an unsigned
 	 * long. Check this here to prevent the fan running at a too low
 	 * frequency.
 	 */
-	if (state.period > ULONG_MAX / MAX_PWM + 1) {
+	if (ctx->pwm_state.period > ULONG_MAX / MAX_PWM + 1) {
 		dev_err(dev, "Configured period too big\n");
 		return -EINVAL;
 	}
 
-	/* Set duty cycle to maximum allowed and enable PWM output */
-	state.duty_cycle = ctx->pwm->args.period - 1;
-	state.enabled = true;
+	ctx->enable_mode = pwm_disable_reg_enable;
 
-	ret = pwm_apply_state(ctx->pwm, &state);
+	/*
+	 * Set duty cycle to maximum allowed and enable PWM output as well as
+	 * the regulator. In case of error nothing is changed
+	 */
+	ret = set_pwm(ctx, MAX_PWM);
 	if (ret) {
 		dev_err(dev, "Failed to configure PWM: %d\n", ret);
 		return ret;
 	}
 	timer_setup(&ctx->rpm_timer, sample_timer, 0);
-	ret = devm_add_action_or_reset(dev, pwm_fan_pwm_disable, ctx);
+	ret = devm_add_action_or_reset(dev, pwm_fan_cleanup, ctx);
 	if (ret)
 		return ret;
 
-	of_property_read_u32(dev->of_node, "pulses-per-revolution", &ppr);
-	ctx->pulses_per_revolution = ppr;
-	if (!ctx->pulses_per_revolution) {
-		dev_err(dev, "pulses-per-revolution can't be zero.\n");
-		return -EINVAL;
+	ctx->tach_count = platform_irq_count(pdev);
+	if (ctx->tach_count < 0)
+		return dev_err_probe(dev, ctx->tach_count,
+				     "Could not get number of fan tachometer inputs\n");
+	dev_dbg(dev, "%d fan tachometer inputs\n", ctx->tach_count);
+
+	if (ctx->tach_count) {
+		channel_count++;	/* We also have a FAN channel. */
+
+		ctx->tachs = devm_kcalloc(dev, ctx->tach_count,
+					  sizeof(struct pwm_fan_tach),
+					  GFP_KERNEL);
+		if (!ctx->tachs)
+			return -ENOMEM;
+
+		ctx->fan_channel.type = hwmon_fan;
+		fan_channel_config = devm_kcalloc(dev, ctx->tach_count + 1,
+						  sizeof(u32), GFP_KERNEL);
+		if (!fan_channel_config)
+			return -ENOMEM;
+		ctx->fan_channel.config = fan_channel_config;
 	}
 
-	if (ctx->irq > 0) {
-		ret = devm_request_irq(dev, ctx->irq, pulse_handler, 0,
-				       pdev->name, ctx);
-		if (ret) {
-			dev_err(dev, "Failed to request interrupt: %d\n", ret);
-			return ret;
+	channels = devm_kcalloc(dev, channel_count + 1,
+				sizeof(struct hwmon_channel_info *), GFP_KERNEL);
+	if (!channels)
+		return -ENOMEM;
+
+	channels[0] = HWMON_CHANNEL_INFO(pwm, HWMON_PWM_INPUT | HWMON_PWM_ENABLE);
+
+	for (i = 0; i < ctx->tach_count; i++) {
+		struct pwm_fan_tach *tach = &ctx->tachs[i];
+		u32 ppr = 2;
+
+		tach->irq = platform_get_irq(pdev, i);
+		if (tach->irq == -EPROBE_DEFER)
+			return tach->irq;
+		if (tach->irq > 0) {
+			ret = devm_request_irq(dev, tach->irq, pulse_handler, 0,
+					       pdev->name, tach);
+			if (ret) {
+				dev_err(dev,
+					"Failed to request interrupt: %d\n",
+					ret);
+				return ret;
+			}
+		}
+
+		of_property_read_u32_index(dev->of_node,
+					   "pulses-per-revolution",
+					   i,
+					   &ppr);
+		tach->pulses_per_revolution = ppr;
+		if (!tach->pulses_per_revolution) {
+			dev_err(dev, "pulses-per-revolution can't be zero.\n");
+			return -EINVAL;
 		}
+
+		fan_channel_config[i] = HWMON_F_INPUT;
+
+		dev_dbg(dev, "tach%d: irq=%d, pulses_per_revolution=%d\n",
+			i, tach->irq, tach->pulses_per_revolution);
+	}
+
+	if (ctx->tach_count > 0) {
 		ctx->sample_start = ktime_get();
 		mod_timer(&ctx->rpm_timer, jiffies + HZ);
+
+		channels[1] = &ctx->fan_channel;
 	}
 
-	hwmon = devm_hwmon_device_register_with_groups(dev, "pwmfan",
-						       ctx, pwm_fan_groups);
+	ctx->info.ops = &pwm_fan_hwmon_ops;
+	ctx->info.info = channels;
+
+	hwmon = devm_hwmon_device_register_with_info(dev, "pwmfan",
+						     ctx, &ctx->info, NULL);
 	if (IS_ERR(hwmon)) {
 		dev_err(dev, "Failed to register hwmon device\n");
 		return PTR_ERR(hwmon);
@@ -481,9 +732,12 @@ static int pwm_fan_probe(struct platform_device *pdev)
 		ret = pwm_fan_register_thermal_notifier(dev, ctx);
 		if (ret)
 			dev_err(dev, "Failed to register thermal notifier: %d\n", ret);
-		else
+		else {
+			device_property_read_u32(dev, "rockchip,hold-time-ms", &ctx->delay_ms);
+			/* keep running at 1000ms on startup */
+			ctx->time_in_state = ktime_add_ms(ktime_get(), ctx->delay_ms + 1000);
 			ctx->thermal_notifier_is_ok = true;
-		return 0;
+		}
 	}
 	if (IS_ENABLED(CONFIG_THERMAL)) {
 		cdev = devm_thermal_of_cooling_device_register(dev,
@@ -496,78 +750,49 @@ static int pwm_fan_probe(struct platform_device *pdev)
 			return ret;
 		}
 		ctx->cdev = cdev;
-		thermal_cdev_update(cdev);
 	}
 
 	return 0;
 }
 
-static int pwm_fan_disable(struct device *dev)
+static int pwm_fan_remove(struct platform_device *pdev)
 {
-	struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
-	struct pwm_args args;
-	int ret;
+	struct pwm_fan_ctx *ctx = platform_get_drvdata(pdev);
 
-	pwm_get_args(ctx->pwm, &args);
-
-	if (ctx->pwm_value || ctx->thermal_notifier_is_ok) {
-		ret = pwm_config(ctx->pwm, 0, args.period);
-		if (ret < 0)
-			return ret;
-
-		pwm_disable(ctx->pwm);
+	if (ctx->thermal_notifier_is_ok) {
+		ctx->thermal_notifier_is_ok = false;
+		rockchip_system_monitor_unregister_notifier(&ctx->thermal_nb);
 	}
 
-	if (ctx->reg_en) {
-		ret = regulator_disable(ctx->reg_en);
-		if (ret) {
-			dev_err(dev, "Failed to disable fan supply: %d\n", ret);
-			return ret;
-		}
-	}
+	pwm_fan_switch_power(ctx, false);
 
 	return 0;
 }
 
 static void pwm_fan_shutdown(struct platform_device *pdev)
 {
-	pwm_fan_disable(&pdev->dev);
+	struct pwm_fan_ctx *ctx = platform_get_drvdata(pdev);
+
+	pwm_fan_cleanup(ctx);
 }
 
-#ifdef CONFIG_PM_SLEEP
 static int pwm_fan_suspend(struct device *dev)
 {
-	return pwm_fan_disable(dev);
+	struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
+
+	return pwm_fan_power_off(ctx);
 }
 
 static int pwm_fan_resume(struct device *dev)
 {
 	struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
-	struct pwm_args pargs;
-	unsigned long duty;
-	int ret;
 
-	if (ctx->reg_en) {
-		ret = regulator_enable(ctx->reg_en);
-		if (ret) {
-			dev_err(dev, "Failed to enable fan supply: %d\n", ret);
-			return ret;
-		}
-	}
-
-	if (ctx->pwm_value == 0 && !ctx->thermal_notifier_is_ok)
-		return 0;
-
-	pwm_get_args(ctx->pwm, &pargs);
-	duty = DIV_ROUND_UP_ULL(ctx->pwm_value * (pargs.period - 1), MAX_PWM);
-	ret = pwm_config(ctx->pwm, duty, pargs.period);
-	if (ret)
-		return ret;
-	return pwm_enable(ctx->pwm);
+	return set_pwm(ctx, ctx->pwm_value);
 }
-#endif
 
-static SIMPLE_DEV_PM_OPS(pwm_fan_pm, pwm_fan_suspend, pwm_fan_resume);
+static const struct dev_pm_ops pwm_fan_pm = {
+	SET_SYSTEM_SLEEP_PM_OPS(pwm_fan_suspend, pwm_fan_resume)
+};
 
 static const struct of_device_id of_pwm_fan_match[] = {
 	{ .compatible = "pwm-fan", },
@@ -577,6 +802,7 @@ MODULE_DEVICE_TABLE(of, of_pwm_fan_match);
 
 static struct platform_driver pwm_fan_driver = {
 	.probe		= pwm_fan_probe,
+	.remove		= pwm_fan_remove,
 	.shutdown	= pwm_fan_shutdown,
 	.driver	= {
 		.name		= "pwm-fan",
diff --git a/kernel-5.10/drivers/media/usb/uvc/Kconfig b/kernel-5.10/drivers/media/usb/uvc/Kconfig
index 4c2f4a3216f..2f853ad6186 100644
--- a/kernel-5.10/drivers/media/usb/uvc/Kconfig
+++ b/kernel-5.10/drivers/media/usb/uvc/Kconfig
@@ -19,3 +19,14 @@ config USB_VIDEO_CLASS_INPUT_EVDEV
 	  to report button events.
 
 	  If you are in doubt, say Y.
+
+config USB_VIDEO_CLASS_REALSENSE
+	bool "Workaround for Intel RealSense depth camera"
+	default n
+	depends on USB_VIDEO_CLASS
+	help
+	  This option increases the UVC_URBS and UVC_MAX_STATUS_SIZE like
+	  librealsense patches does.
+
+	  Link: https://github.com/IntelRealSense/librealsense
+	  If you are in doubt, say N.
diff --git a/kernel-5.10/drivers/media/usb/uvc/uvc_driver.c b/kernel-5.10/drivers/media/usb/uvc/uvc_driver.c
index 34b1ca6e889..0c4c3ee9349 100644
--- a/kernel-5.10/drivers/media/usb/uvc/uvc_driver.c
+++ b/kernel-5.10/drivers/media/usb/uvc/uvc_driver.c
@@ -170,6 +170,11 @@ static struct uvc_format_desc uvc_fmts[] = {
 		.guid		= UVC_GUID_FORMAT_Y12I,
 		.fcc		= V4L2_PIX_FMT_Y12I,
 	},
+	{
+		.name		= "Greyscale 16 L/R (Y16I)",
+		.guid		= UVC_GUID_FORMAT_Y16I,
+		.fcc		= V4L2_PIX_FMT_Y16I,
+	},
 	{
 		.name		= "Depth data 16-bit (Z16)",
 		.guid		= UVC_GUID_FORMAT_Z16,
@@ -225,6 +230,58 @@ static struct uvc_format_desc uvc_fmts[] = {
 		.guid		= UVC_GUID_FORMAT_HEVC,
 		.fcc		= V4L2_PIX_FMT_HEVC,
 	},
+	{
+		.name		= "Depth data 16-bit (D16)",
+		.guid		= UVC_GUID_FORMAT_D16,
+		.fcc		= V4L2_PIX_FMT_Z16,
+	},
+	{
+		.name		= "Packed raw data 10-bit",
+		.guid		= UVC_GUID_FORMAT_W10,
+		.fcc		= V4L2_PIX_FMT_W10,
+	},
+	{
+		.name		= "Confidence data (C   )",
+		.guid		= UVC_GUID_FORMAT_CONFIDENCE_MAP,
+		.fcc		= V4L2_PIX_FMT_CONFIDENCE_MAP,
+	},
+	/* FishEye 8-bit monochrome */
+	{
+		.name		= "Raw data 8-bit (RAW8)",
+		.guid		= UVC_GUID_FORMAT_RAW8,
+		.fcc		= V4L2_PIX_FMT_GREY,
+	},
+	/* Legacy formats for backward-compatibility*/
+	{
+		.name		= "Raw data 16-bit (RW16)",
+		.guid		= UVC_GUID_FORMAT_RW16,
+		.fcc		= V4L2_PIX_FMT_RW16,
+	},
+	{
+		.name		= "16-bit Bayer BGBG/GRGR",
+		.guid		= UVC_GUID_FORMAT_BAYER16,
+		.fcc		= V4L2_PIX_FMT_SBGGR16,
+	},
+	{
+		.name		= "Z16 Huffman Compression",
+		.guid		= UVC_GUID_FORMAT_Z16H,
+		.fcc		= V4L2_PIX_FMT_Z16H,
+	},
+	{
+		.name		= "Frame Grabber (FG  )",
+		.guid		= UVC_GUID_FORMAT_FG,
+		.fcc		= V4L2_PIX_FMT_FG,
+	},
+	{
+		.name		= "SR300 Depth/Confidence (INZC)",
+		.guid		= UVC_GUID_FORMAT_INZC,
+		.fcc		= V4L2_PIX_FMT_INZC,
+	},
+	{
+		.name		= "Relative IR (PAIR)",
+		.guid		= UVC_GUID_FORMAT_PAIR,
+		.fcc		= V4L2_PIX_FMT_PAIR,
+	},
 };
 
 /* ------------------------------------------------------------------------
@@ -3014,6 +3071,276 @@ static const struct usb_device_id uvc_ids[] = {
 	  .bInterfaceSubClass	= 1,
 	  .bInterfaceProtocol	= 0,
 	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel SR306 depth camera */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0aa3,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel SR300 depth camera */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0aa5,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel D400/PSR depth camera*/
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0ad1,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel D410/ASR depth camera */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0ad2,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel D415/ASRC depth camera */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0ad3,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel D430/AWG depth camera */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0ad4,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel D450/AWGT depth camera */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0ad5,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* USB2 Descriptor, Depth Sensor */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0ad6,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel D400 IMU Module */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0af2,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel D420/PWG depth camera */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0af6,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel D420_MM/PWGT depth camera */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0afe,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel D410_MM/ASRT depth camera */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0aff,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel D400_MM/PSRT depth camera */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0b00,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel D430_MM/AWGCT depth camera */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0b01,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel D460/DS5U depth camera */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0b03,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel D435/AWGC depth camera */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0b07,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel D405 S depth camera */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0b0c,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel L500 depth camera */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0b0d,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel D435i depth camera */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0b3a,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel L515 Pre-PRQ */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0b3d,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel SR305 Depth Camera*/
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0b48,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel D416 Depth Camera */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0b49,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel D430i depth camera */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0b4b,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel D465 */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0b4d,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel D405 */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0b5b,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel D455 */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0b5c,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel L515 */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0b64,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel L535 */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0b68,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel D585 Depth Camera */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0b6a,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
+	/* Intel S585 Safety Camera */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor			= 0x8086,
+	  .idProduct		= 0x0b6b,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_META(V4L2_META_FMT_D4XX) },
 	/* Generic USB Video Class */
 	{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_UNDEFINED) },
 	{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_15) },
diff --git a/kernel-5.10/drivers/media/usb/uvc/uvcvideo.h b/kernel-5.10/drivers/media/usb/uvc/uvcvideo.h
index 372de342807..66b25296e94 100644
--- a/kernel-5.10/drivers/media/usb/uvc/uvcvideo.h
+++ b/kernel-5.10/drivers/media/usb/uvc/uvcvideo.h
@@ -142,6 +142,9 @@
 #define UVC_GUID_FORMAT_Y12I \
 	{ 'Y',  '1',  '2',  'I', 0x00, 0x00, 0x10, 0x00, \
 	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_Y16I \
+	{ 'Y',  '1',  '6',  'I', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
 #define UVC_GUID_FORMAT_Z16 \
 	{ 'Z',  '1',  '6',  ' ', 0x00, 0x00, 0x10, 0x00, \
 	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
@@ -172,6 +175,38 @@
 	{ 'H',  'E',  'V',  'C', 0x00, 0x00, 0x10, 0x00, \
 	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
 
+#define UVC_GUID_FORMAT_D16 \
+	{ 'P', 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_W10 \
+	{ 'W',  '1',  '0',  ' ', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_RAW8 \
+	{ 'R',  'A',  'W',  '8', 0x66, 0x1a, 0x42, 0xa2, \
+	 0x90, 0x65, 0xd0, 0x18, 0x14, 0xa8, 0xef, 0x8a}
+#define UVC_GUID_FORMAT_CONFIDENCE_MAP \
+	{ 'C',  ' ',  ' ',  ' ', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+/* Legacy formats */
+#define UVC_GUID_FORMAT_RW16 \
+	{ 'R',  'W',  '1',  '6', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_BAYER16 \
+	{ 'R',  'W',  '1',  '6', 0x66, 0x1a, 0x42, 0xa2, \
+	 0x90, 0x65, 0xd0, 0x18, 0x14, 0xa8, 0xef, 0x8a}
+#define UVC_GUID_FORMAT_Z16H \
+	{ 'Z',  '1',  '6',  'H', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_FG \
+	{ 'F',  'G',  ' ',  ' ', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_INZC \
+	{ 'I',  'N',  'Z',  'C', 0x02, 0xb6, 0x0f, 0x48, \
+	 0x97, 0x8c, 0xe4, 0xe8, 0x8a, 0xe8, 0x9b, 0x89}
+#define UVC_GUID_FORMAT_PAIR \
+	{ 'P',  'A',  'I',  'R', 0x36, 0x85, 0x41, 0x48, \
+	 0xb6, 0xbf, 0x8f, 0xc6, 0xff, 0xb0, 0x83, 0xa8}
+
 
 /* ------------------------------------------------------------------------
  * Driver specific constants.
@@ -180,11 +215,19 @@
 #define DRIVER_VERSION		"1.1.1"
 
 /* Number of isochronous URBs. */
+#ifdef CONFIG_USB_VIDEO_CLASS_REALSENSE
+#define UVC_URBS		16
+#else
 #define UVC_URBS		5
+#endif
 /* Maximum number of packets per URB. */
 #define UVC_MAX_PACKETS		32
 /* Maximum status buffer size in bytes of interrupt URB. */
+#ifdef CONFIG_USB_VIDEO_CLASS_REALSENSE
+#define UVC_MAX_STATUS_SIZE	32
+#else
 #define UVC_MAX_STATUS_SIZE	16
+#endif
 
 #define UVC_CTRL_CONTROL_TIMEOUT	5000
 #define UVC_CTRL_STREAMING_TIMEOUT	5000
diff --git a/kernel-5.10/drivers/media/v4l2-core/v4l2-ioctl.c b/kernel-5.10/drivers/media/v4l2-core/v4l2-ioctl.c
index 2b94f62e71a..43ff80799d1 100644
--- a/kernel-5.10/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/kernel-5.10/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1314,6 +1314,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
 	case V4L2_PIX_FMT_Y10P:		descr = "10-bit Greyscale (MIPI Packed)"; break;
 	case V4L2_PIX_FMT_Y8I:		descr = "Interleaved 8-bit Greyscale"; break;
 	case V4L2_PIX_FMT_Y12I:		descr = "Interleaved 12-bit Greyscale"; break;
+	case V4L2_PIX_FMT_Y16I:		descr = "Interleaved 16-bit Greyscale"; break;
 	case V4L2_PIX_FMT_Z16:		descr = "16-bit Depth"; break;
 	case V4L2_PIX_FMT_INZI:		descr = "Planar 10:16 Greyscale Depth"; break;
 	case V4L2_PIX_FMT_CNF4:		descr = "4-bit Depth Confidence (Packed)"; break;
@@ -1431,6 +1432,14 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
 	case V4L2_META_FMT_UVC:		descr = "UVC Payload Header Metadata"; break;
 	case V4L2_META_FMT_D4XX:	descr = "Intel D4xx UVC Metadata"; break;
 	case V4L2_META_FMT_VIVID:       descr = "Vivid Metadata"; break;
+	/* Librealsense formats*/
+	case V4L2_PIX_FMT_RW16:		descr = "16-bit Raw data"; break;
+	case V4L2_PIX_FMT_W10:		descr = "10-bit packed 8888[2222]"; break;
+	case V4L2_PIX_FMT_CONFIDENCE_MAP:	descr = "Packed [44] confidence data"; break;
+	case V4L2_PIX_FMT_FG:		descr = "Frame Grabber (FG  )"; break;
+	case V4L2_PIX_FMT_INZC:		descr = "Planar Depth/Confidence (INZC)"; break;
+	case V4L2_PIX_FMT_PAIR:		descr = "Relative IR (PAIR)"; break;
+	case V4L2_PIX_FMT_Z16H:		descr = "Z16 Huffman Compression"; break;
 
 	default:
 		/* Compressed formats */
diff --git a/kernel-5.10/drivers/power/supply/Kconfig b/kernel-5.10/drivers/power/supply/Kconfig
index 2d1539d25f1..6ed4bf972c8 100644
--- a/kernel-5.10/drivers/power/supply/Kconfig
+++ b/kernel-5.10/drivers/power/supply/Kconfig
@@ -870,4 +870,12 @@ config CHARGER_SGM41542
 	help
 	  Say Y to enable support for the SGM41542 battery charger.
 
+config SIMPLE_ADC_POWER
+	tristate "Simple ADC power supply driver"
+	depends on IIO
+	default y if VENDOR_FRIENDLYELEC
+	help
+	  Say Y here to enable support for the simple power supply driver
+	  which uses IIO framework to read adc.
+
 endif # POWER_SUPPLY
diff --git a/kernel-5.10/drivers/power/supply/Makefile b/kernel-5.10/drivers/power/supply/Makefile
index 4d1d8cbaf1c..6739e2d4b59 100644
--- a/kernel-5.10/drivers/power/supply/Makefile
+++ b/kernel-5.10/drivers/power/supply/Makefile
@@ -8,6 +8,7 @@ power_supply-$(CONFIG_LEDS_TRIGGERS)	+= power_supply_leds.o
 obj-$(CONFIG_POWER_SUPPLY)	+= power_supply.o
 obj-$(CONFIG_POWER_SUPPLY_HWMON) += power_supply_hwmon.o
 obj-$(CONFIG_GENERIC_ADC_BATTERY)	+= generic-adc-battery.o
+obj-$(CONFIG_SIMPLE_ADC_POWER)	+= simple_adc_power.o
 
 obj-$(CONFIG_PDA_POWER)		+= pda_power.o
 obj-$(CONFIG_APM_POWER)		+= apm_power.o
diff --git a/kernel-5.10/drivers/power/supply/simple_adc_power.c b/kernel-5.10/drivers/power/supply/simple_adc_power.c
new file mode 100644
index 00000000000..b7bbbd04127
--- /dev/null
+++ b/kernel-5.10/drivers/power/supply/simple_adc_power.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Simple ADC power supply driver
+ *
+ * Copyright (c) 2024 FriendlyElec Computer Tech. Co., Ltd.
+ * (http://www.friendlyelec.com)
+ *
+ * based on ingenic-battery.c
+ */
+
+#include <linux/iio/consumer.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+
+struct sadc_power_priv {
+	struct device *dev;
+	struct iio_channel *iio_v;
+	struct power_supply_desc desc;
+	struct power_supply *psy;
+	struct power_supply_battery_info info;
+	const struct sadc_platform_data *pdata;
+	int online;
+};
+
+struct sadc_platform_data {
+	int (*to_voltage)(int raw);
+};
+
+static int sadc_power_get_property(struct power_supply *psy,
+				   enum power_supply_property psp,
+				   union power_supply_propval *val)
+{
+	struct sadc_power_priv *priv = power_supply_get_drvdata(psy);
+	struct power_supply_battery_info *info = &priv->info;
+	int raw = 0;
+	int ret;
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_HEALTH:
+		ret = iio_read_channel_raw(priv->iio_v, &raw);
+		val->intval = priv->pdata->to_voltage(raw);
+		if (val->intval < info->voltage_min_design_uv)
+			val->intval = POWER_SUPPLY_HEALTH_DEAD;
+		else if (val->intval > info->voltage_max_design_uv)
+			val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+		else
+			val->intval = POWER_SUPPLY_HEALTH_GOOD;
+		return ret < 0 ? ret : 0;
+	case POWER_SUPPLY_PROP_ONLINE:
+		val->intval = priv->online;
+		return 0;
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		ret = iio_read_channel_raw(priv->iio_v, &raw);
+		val->intval = priv->pdata->to_voltage(raw);
+		return ret < 0 ? ret : 0;
+	case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+		val->intval = info->voltage_min_design_uv;
+		return 0;
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+		val->intval = info->voltage_max_design_uv;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static enum power_supply_property sadc_power_properties[] = {
+	POWER_SUPPLY_PROP_HEALTH,
+	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+	POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+};
+
+static int sadc_to_voltage_v1(int raw) {
+	int mv = 5000;
+
+	if (raw > 160 && raw < 1024) {
+		mv = raw * 196 - 2130;
+		mv /= 10;
+	}
+
+	return (mv * 1000);
+}
+
+static int sadc_to_voltage_v2(int raw) {
+	int mv = raw * 2475 / 512;
+
+	return (mv * 1000);
+}
+
+static const struct sadc_platform_data sadc_pdata_v1 = {
+	.to_voltage = sadc_to_voltage_v1,
+};
+
+static const struct sadc_platform_data sadc_pdata_v2 = {
+	.to_voltage = sadc_to_voltage_v2,
+};
+
+static const struct of_device_id sadc_power_of_match[] = {
+	{ .compatible = "simple-adc-power-v1", .data = &sadc_pdata_v1 },
+	{ .compatible = "simple-adc-power-v2", .data = &sadc_pdata_v2 },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, sadc_power_of_match);
+
+static int sadc_power_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	const struct of_device_id *match;
+	struct sadc_power_priv *priv;
+	struct power_supply_config psy_cfg = {};
+	struct power_supply_desc *desc;
+	int ret;
+
+	match = of_match_device(sadc_power_of_match, dev);
+	if (!match || !match->data)
+		return -ENODEV;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = dev;
+	priv->online = 1;
+	priv->pdata = match->data;
+
+	priv->iio_v = devm_iio_channel_get(dev, "voltage");
+	if (IS_ERR(priv->iio_v))
+		return PTR_ERR(priv->iio_v);
+
+	desc = &priv->desc;
+	desc->name = dev_name(dev);
+	desc->type = POWER_SUPPLY_TYPE_MAINS;
+	desc->properties = sadc_power_properties;
+	desc->num_properties = ARRAY_SIZE(sadc_power_properties);
+	desc->get_property = sadc_power_get_property;
+
+	psy_cfg.drv_data = priv;
+	psy_cfg.of_node = dev->of_node;
+
+	priv->psy = devm_power_supply_register(dev, desc, &psy_cfg);
+	if (IS_ERR(priv->psy))
+		return dev_err_probe(dev, PTR_ERR(priv->psy),
+				     "Unable to register supply\n");
+
+	ret = power_supply_get_battery_info(priv->psy, &priv->info);
+	if (ret) {
+		dev_err(dev, "Unable to get battery info: %d\n", ret);
+		return ret;
+	}
+	if (priv->info.voltage_min_design_uv < 0) {
+		dev_err(dev, "Unable to get voltage min design\n");
+		return priv->info.voltage_min_design_uv;
+	}
+	if (priv->info.voltage_max_design_uv < 0) {
+		dev_err(dev, "Unable to get voltage max design\n");
+		return priv->info.voltage_max_design_uv;
+	}
+
+	return 0;
+}
+
+static struct platform_driver sadc_power_driver = {
+	.driver = {
+		.name = "simple-adc-power",
+		.of_match_table = of_match_ptr(sadc_power_of_match),
+	},
+	.probe = sadc_power_probe,
+};
+module_platform_driver(sadc_power_driver);
+
+MODULE_ALIAS("platform:simple-adc-power");
+MODULE_AUTHOR("support@friendlyarm.com");
+MODULE_DESCRIPTION("Simple ADC power supply driver");
+MODULE_LICENSE("GPL");
diff --git a/kernel-5.10/drivers/power/supply/test_power.c b/kernel-5.10/drivers/power/supply/test_power.c
index adac25e9a61..f86b66d53da 100644
--- a/kernel-5.10/drivers/power/supply/test_power.c
+++ b/kernel-5.10/drivers/power/supply/test_power.c
@@ -28,7 +28,7 @@ enum test_power_id {
 
 static int ac_online			= 1;
 static int usb_online			= 1;
-static int battery_status		= POWER_SUPPLY_STATUS_DISCHARGING;
+static int battery_status		= POWER_SUPPLY_STATUS_FULL;
 static int battery_health		= POWER_SUPPLY_HEALTH_GOOD;
 static int battery_present		= 1; /* true */
 static int battery_technology		= POWER_SUPPLY_TECHNOLOGY_LION;
diff --git a/kernel-5.10/include/soc/rockchip/rockchip_dmc.h b/kernel-5.10/include/soc/rockchip/rockchip_dmc.h
index 634f5f3f359..e3cc9306f71 100644
--- a/kernel-5.10/include/soc/rockchip/rockchip_dmc.h
+++ b/kernel-5.10/include/soc/rockchip/rockchip_dmc.h
@@ -118,7 +118,7 @@ rockchip_dmcfreq_vop_bandwidth_init(struct dmcfreq_common_info *info)
 {
 }
 
-bool inline int rockchip_dmcfreq_vop_bandwidth_avail(void)
+static inline bool rockchip_dmcfreq_vop_bandwidth_avail(void)
 {
 	return false;
 }
diff --git a/kernel-5.10/include/uapi/linux/videodev2.h b/kernel-5.10/include/uapi/linux/videodev2.h
index 514db71fb83..a9380872a2a 100644
--- a/kernel-5.10/include/uapi/linux/videodev2.h
+++ b/kernel-5.10/include/uapi/linux/videodev2.h
@@ -736,11 +736,20 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_S5C_UYVY_JPG v4l2_fourcc('S', '5', 'C', 'I') /* S5C73M3 interleaved UYVY/JPEG */
 #define V4L2_PIX_FMT_Y8I      v4l2_fourcc('Y', '8', 'I', ' ') /* Greyscale 8-bit L/R interleaved */
 #define V4L2_PIX_FMT_Y12I     v4l2_fourcc('Y', '1', '2', 'I') /* Greyscale 12-bit L/R interleaved */
+#define V4L2_PIX_FMT_Y16I     v4l2_fourcc('Y', '1', '6', 'I') /* Greyscale 16-bit L/R interleaved */
 #define V4L2_PIX_FMT_Z16      v4l2_fourcc('Z', '1', '6', ' ') /* Depth data 16-bit */
 #define V4L2_PIX_FMT_MT21C    v4l2_fourcc('M', 'T', '2', '1') /* Mediatek compressed block mode  */
 #define V4L2_PIX_FMT_INZI     v4l2_fourcc('I', 'N', 'Z', 'I') /* Intel Planar Greyscale 10-bit and Depth 16-bit */
 #define V4L2_PIX_FMT_SUNXI_TILED_NV12 v4l2_fourcc('S', 'T', '1', '2') /* Sunxi Tiled NV12 Format */
 #define V4L2_PIX_FMT_CNF4     v4l2_fourcc('C', 'N', 'F', '4') /* Intel 4-bit packed depth confidence information */
+/* Librealsense development */
+#define V4L2_PIX_FMT_RW16     v4l2_fourcc('R', 'W', '1', '6') /* Raw data 16-bit */
+#define V4L2_PIX_FMT_W10      v4l2_fourcc('W', '1', '0', ' ') /* Packed raw data 10-bit */
+#define V4L2_PIX_FMT_CONFIDENCE_MAP    v4l2_fourcc('C', ' ', ' ', ' ') /* Two pixels in one byte */
+#define V4L2_PIX_FMT_FG       v4l2_fourcc('F', 'G', ' ', ' ') /* Frame Grabber */
+#define V4L2_PIX_FMT_INZC     v4l2_fourcc('I', 'N', 'Z', 'C') /* Planar Depth/Confidence */
+#define V4L2_PIX_FMT_PAIR     v4l2_fourcc('P', 'A', 'I', 'R') /* Relative IR */
+#define V4L2_PIX_FMT_Z16H     v4l2_fourcc('Z', '1', '6', 'H') /* Depth Z16 custom Huffman Code compression*/
 
 /* 10bit raw bayer packed, 32 bytes for every 25 pixels, last LSB 6 bits unused */
 #define V4L2_PIX_FMT_IPU3_SBGGR10	v4l2_fourcc('i', 'p', '3', 'b') /* IPU3 packed 10-bit BGGR bayer */