From d8e42edcd660498d2361dd77503cf1165579df04 Mon Sep 17 00:00:00 2001 From: Damon Ding Date: Mon, 30 Jun 2025 17:28:31 +0800 Subject: [PATCH 01/15] drm/rockchip: Pass struct rockchip_drm_sub_dev for &rockchip_drm_sub_dev.loader_protect() In order to enhance the flexibility of loader protect callback &rockchip_drm_sub_dev.loader_protect(), we replace the parameter 'struct drm_encoder *encoder' by 'struct rockchip_drm_sub_dev'so that the panel or bridge drivers can apply it to achieve the loader protect function. Change-Id: Ic26110583245c1a0807fee35f4dd889ee8f1f845 Signed-off-by: Damon Ding --- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 6 +++--- drivers/gpu/drm/rockchip/dw-dp.c | 4 ++-- drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c | 7 ++++--- drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c | 5 ++--- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 4 ++-- drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 2 +- drivers/gpu/drm/rockchip/rockchip_drm_logo.c | 4 ++-- drivers/gpu/drm/rockchip/rockchip_drm_tve.c | 4 ++-- drivers/gpu/drm/rockchip/rockchip_lvds.c | 5 ++--- drivers/gpu/drm/rockchip/rockchip_rgb.c | 5 ++--- 10 files changed, 22 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 2183c8a8d076..2ed0c87caa94 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -251,9 +251,9 @@ static int rockchip_dp_get_modes(struct analogix_dp_plat_data *plat_data, return 0; } -static int rockchip_dp_loader_protect(struct drm_encoder *encoder, bool on) +static int rockchip_dp_loader_protect(struct rockchip_drm_sub_dev *sub_dev, bool on) { - struct rockchip_dp_device *dp = encoder_to_dp(encoder); + struct rockchip_dp_device *dp = container_of(sub_dev, struct rockchip_dp_device, sub_dev); struct analogix_dp_plat_data *plat_data = &dp->plat_data; struct rockchip_dp_device *secondary = NULL; int ret; @@ -261,7 +261,7 @@ static int rockchip_dp_loader_protect(struct drm_encoder *encoder, bool on) if (plat_data->right) { secondary = rockchip_dp_find_by_id(dp->dev->driver, !dp->id); - ret = rockchip_dp_loader_protect(&secondary->encoder.encoder, on); + ret = rockchip_dp_loader_protect(&secondary->sub_dev, on); if (ret) return ret; } diff --git a/drivers/gpu/drm/rockchip/dw-dp.c b/drivers/gpu/drm/rockchip/dw-dp.c index 4b79fa4cce6e..27772ccabdaa 100644 --- a/drivers/gpu/drm/rockchip/dw-dp.c +++ b/drivers/gpu/drm/rockchip/dw-dp.c @@ -3308,9 +3308,9 @@ static void _dw_dp_loader_protect(struct dw_dp *dp, bool on) } } -static int dw_dp_loader_protect(struct drm_encoder *encoder, bool on) +static int dw_dp_loader_protect(struct rockchip_drm_sub_dev *sub_dev, bool on) { - struct dw_dp *dp = encoder_to_dp(encoder); + struct dw_dp *dp = container_of(sub_dev, struct dw_dp, sub_dev); dp->is_loader_protect = true; _dw_dp_loader_protect(dp, on); diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c index e9f612a7f6f0..9f355f7e13cc 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c @@ -914,10 +914,11 @@ static void dw_mipi_dsi_rockchip_loader_protect(struct dw_mipi_dsi_rockchip *dsi dw_mipi_dsi_rockchip_loader_protect(dsi->slave, on); } -static int dw_mipi_dsi_rockchip_encoder_loader_protect(struct drm_encoder *encoder, - bool on) +static int dw_mipi_dsi_rockchip_encoder_loader_protect(struct rockchip_drm_sub_dev *sub_dev, + bool on) { - struct dw_mipi_dsi_rockchip *dsi = to_dsi(encoder); + struct dw_mipi_dsi_rockchip *dsi = container_of(sub_dev, struct dw_mipi_dsi_rockchip, + sub_dev); if (dsi->panel) panel_simple_loader_protect(dsi->panel); diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c index 3abd81a8481b..edd3c32f9aba 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c @@ -1191,10 +1191,9 @@ static void dw_mipi_dsi2_loader_protect(struct dw_mipi_dsi2 *dsi2, bool on) dw_mipi_dsi2_loader_protect(dsi2->slave, on); } -static int dw_mipi_dsi2_encoder_loader_protect(struct drm_encoder *encoder, - bool on) +static int dw_mipi_dsi2_encoder_loader_protect(struct rockchip_drm_sub_dev *sub_dev, bool on) { - struct dw_mipi_dsi2 *dsi2 = encoder_to_dsi2(encoder); + struct dw_mipi_dsi2 *dsi2 = container_of(sub_dev, struct dw_mipi_dsi2, sub_dev); if (dsi2->panel) panel_simple_loader_protect(dsi2->panel); diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index c29caa36b004..f77b349f5187 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -2153,9 +2153,9 @@ static int _dw_hdmi_rockchip_encoder_loader_protect(struct rockchip_hdmi *hdmi, return 0; } -static int dw_hdmi_rockchip_encoder_loader_protect(struct drm_encoder *encoder, bool on) +static int dw_hdmi_rockchip_encoder_loader_protect(struct rockchip_drm_sub_dev *sub_dev, bool on) { - struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); + struct rockchip_hdmi *hdmi = container_of(sub_dev, struct rockchip_hdmi, sub_dev); struct rockchip_hdmi *secondary; _dw_hdmi_rockchip_encoder_loader_protect(hdmi, on); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index 665f65181963..35e56f25dd7e 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -144,7 +144,7 @@ struct rockchip_drm_sub_dev { struct list_head list; struct drm_connector *connector; struct device_node *of_node; - int (*loader_protect)(struct drm_encoder *encoder, bool on); + int (*loader_protect)(struct rockchip_drm_sub_dev *sub_dev, bool on); void (*update_vfp_for_vrr)(struct drm_connector *connector, struct drm_display_mode *mode, int vfp); }; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_logo.c b/drivers/gpu/drm/rockchip/rockchip_drm_logo.c index 79f39cd371bf..9d74f40a0350 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_logo.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_logo.c @@ -813,7 +813,7 @@ static int setup_initial_state(struct drm_device *drm_dev, conn_state->best_encoder = rockchip_drm_connector_get_single_encoder(connector); if (set->sub_dev->loader_protect) { - ret = set->sub_dev->loader_protect(conn_state->best_encoder, true); + ret = set->sub_dev->loader_protect(set->sub_dev, true); if (ret) { dev_err(drm_dev->dev, "connector[%s] loader protect failed\n", @@ -979,7 +979,7 @@ error_crtc: priv->crtc_funcs[pipe]->loader_protect(crtc, false, NULL); error_conn: if (set->sub_dev->loader_protect) - set->sub_dev->loader_protect(conn_state->best_encoder, false); + set->sub_dev->loader_protect(set->sub_dev, false); return ret; } diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_tve.c b/drivers/gpu/drm/rockchip/rockchip_drm_tve.c index f42b294a28a1..c91ebf36a30b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_tve.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_tve.c @@ -546,9 +546,9 @@ rockchip_tve_encoder_atomic_check(struct drm_encoder *encoder, return 0; } -static int rockchip_tve_encoder_loader_protect(struct drm_encoder *encoder, bool on) +static int rockchip_tve_encoder_loader_protect(struct rockchip_drm_sub_dev *sub_dev, bool on) { - struct rockchip_tve *tve = encoder_to_tve(encoder); + struct rockchip_tve *tve = container_of(sub_dev, struct rockchip_tve, sub_dev); int ret; if (on) { diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c index 20d1d9ea1c7a..c063514ab517 100644 --- a/drivers/gpu/drm/rockchip/rockchip_lvds.c +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c @@ -431,10 +431,9 @@ static void rockchip_lvds_encoder_disable(struct drm_encoder *encoder) drm_panel_unprepare(lvds->panel); } -static int rockchip_lvds_encoder_loader_protect(struct drm_encoder *encoder, - bool on) +static int rockchip_lvds_encoder_loader_protect(struct rockchip_drm_sub_dev *sub_dev, bool on) { - struct rockchip_lvds *lvds = encoder_to_lvds(encoder); + struct rockchip_lvds *lvds = container_of(sub_dev, struct rockchip_lvds, sub_dev); if (lvds->panel) panel_simple_loader_protect(lvds->panel); diff --git a/drivers/gpu/drm/rockchip/rockchip_rgb.c b/drivers/gpu/drm/rockchip/rockchip_rgb.c index 89e48f4f2a4d..806092bcab30 100644 --- a/drivers/gpu/drm/rockchip/rockchip_rgb.c +++ b/drivers/gpu/drm/rockchip/rockchip_rgb.c @@ -403,10 +403,9 @@ rockchip_rgb_encoder_atomic_check(struct drm_encoder *encoder, return 0; } -static int rockchip_rgb_encoder_loader_protect(struct drm_encoder *encoder, - bool on) +static int rockchip_rgb_encoder_loader_protect(struct rockchip_drm_sub_dev *sub_dev, bool on) { - struct rockchip_rgb *rgb = encoder_to_rgb(encoder); + struct rockchip_rgb *rgb = container_of(sub_dev, struct rockchip_rgb, sub_dev); if (rgb->np_mcu_panel) { struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(rgb->panel); From 65f19639f903cf5d4f76b70b93f9dfa8749a324c Mon Sep 17 00:00:00 2001 From: Damon Ding Date: Sun, 29 Jun 2025 16:11:58 +0800 Subject: [PATCH 02/15] drm/rockchip: Make the DRM panel as part of Rockchip DRM sub devices for panel loader protect In order to support the loader protect function of more panel drivers, we add the DRM panel as part of Rockchip DRM sub devices. The panel-simple driver always is regarded as a panel driver demo of Rockchip platforms, so we first add the Rockchip DRM sub_dev for it. The panel drivers that adapt to Rockchip DRM drivers can call rockchip_drm_register_sub_dev()/rockchip_drm_unregister_sub_dev() to register/unregister DRM sub_dev, and then invoke rockchip_drm_panel_loader_protect() to achieve the panel loader protect function. Change-Id: Ibc302c3f3677e0c55545e90af29d7a87444c2e21 Signed-off-by: Damon Ding --- drivers/gpu/drm/panel/panel-simple.c | 36 +++++++++++++------ drivers/gpu/drm/panel/panel-simple.h | 19 ---------- .../gpu/drm/rockchip/analogix_dp-rockchip.c | 2 +- .../gpu/drm/rockchip/dw-mipi-dsi-rockchip.c | 2 +- .../gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c | 2 +- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 22 ++++++++++-- drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 4 +-- drivers/gpu/drm/rockchip/rockchip_lvds.c | 2 +- drivers/gpu/drm/rockchip/rockchip_rgb.c | 2 +- 9 files changed, 51 insertions(+), 40 deletions(-) delete mode 100644 drivers/gpu/drm/panel/panel-simple.h diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 6b8e7f3faba0..7b1750e79cbe 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -45,7 +45,7 @@ #include #include -#include "panel-simple.h" +#include "../rockchip/rockchip_drm_drv.h" enum panel_simple_cmd_type { CMD_TYPE_DEFAULT, @@ -220,6 +220,8 @@ struct panel_simple { enum drm_panel_orientation orientation; struct rockchip_panel_notifier panel_notifier; + + struct rockchip_drm_sub_dev sub_dev; }; static inline void panel_simple_msleep(unsigned int msecs) @@ -519,23 +521,29 @@ static int panel_simple_regulator_disable(struct panel_simple *p) return 0; } -int panel_simple_loader_protect(struct drm_panel *panel) +static int panel_simple_loader_protect(struct rockchip_drm_sub_dev *sub_dev, bool on) { - struct panel_simple *p = to_panel_simple(panel); + struct panel_simple *p = container_of(sub_dev, struct panel_simple, sub_dev); int err; - err = panel_simple_regulator_enable(p); - if (err < 0) { - dev_err(panel->dev, "failed to enable supply: %d\n", err); - return err; - } + if (on) { + err = panel_simple_regulator_enable(p); + if (err < 0) { + dev_err(p->base.dev, "failed to enable supply: %d\n", err); + return err; + } - p->prepared = true; - p->enabled = true; + p->prepared = true; + p->enabled = true; + } else { + p->enabled = false; + p->prepared = false; + + panel_simple_regulator_disable(p); + } return 0; } -EXPORT_SYMBOL(panel_simple_loader_protect); static int panel_simple_disable(struct drm_panel *panel) { @@ -1003,6 +1011,10 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) drm_panel_add(&panel->base); + panel->sub_dev.of_node = dev->of_node; + panel->sub_dev.loader_protect = panel_simple_loader_protect; + rockchip_drm_register_sub_dev(&panel->sub_dev); + return 0; free_ddc: @@ -1016,6 +1028,8 @@ static void panel_simple_remove(struct device *dev) { struct panel_simple *panel = dev_get_drvdata(dev); + rockchip_drm_unregister_sub_dev(&panel->sub_dev); + drm_panel_remove(&panel->base); drm_panel_disable(&panel->base); drm_panel_unprepare(&panel->base); diff --git a/drivers/gpu/drm/panel/panel-simple.h b/drivers/gpu/drm/panel/panel-simple.h deleted file mode 100644 index a056f357886a..000000000000 --- a/drivers/gpu/drm/panel/panel-simple.h +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ -/* - * Copyright (c) 2021 Rockchip Electronics Co., Ltd. - * Author: Sandy Huang - */ - -#ifndef PANEL_SIMPLE_H -#define PANEL_SIMPLE_H -#include - -#if IS_REACHABLE(CONFIG_DRM_PANEL_SIMPLE) -int panel_simple_loader_protect(struct drm_panel *panel); -#else -static inline int panel_simple_loader_protect(struct drm_panel *panel) -{ - return 0; -} -#endif -#endif diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 2ed0c87caa94..d511922e7619 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -270,7 +270,7 @@ static int rockchip_dp_loader_protect(struct rockchip_drm_sub_dev *sub_dev, bool return 0; if (plat_data->panel) - panel_simple_loader_protect(plat_data->panel); + rockchip_drm_panel_loader_protect(plat_data->panel, on); ret = analogix_dp_loader_protect(dp->adp); if (ret) { diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c index 9f355f7e13cc..a356d3ffc313 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c @@ -921,7 +921,7 @@ static int dw_mipi_dsi_rockchip_encoder_loader_protect(struct rockchip_drm_sub_d sub_dev); if (dsi->panel) - panel_simple_loader_protect(dsi->panel); + rockchip_drm_panel_loader_protect(dsi->panel, on); dw_mipi_dsi_rockchip_loader_protect(dsi, on); diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c index edd3c32f9aba..8d0d3539b0fb 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c @@ -1196,7 +1196,7 @@ static int dw_mipi_dsi2_encoder_loader_protect(struct rockchip_drm_sub_dev *sub_ struct dw_mipi_dsi2 *dsi2 = container_of(sub_dev, struct dw_mipi_dsi2, sub_dev); if (dsi2->panel) - panel_simple_loader_protect(dsi2->panel); + rockchip_drm_panel_loader_protect(dsi2->panel, on); dw_mipi_dsi2_loader_protect(dsi2, on); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 1aaa4251484d..4288476f8ab6 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -382,7 +382,7 @@ void rockchip_connector_update_vfp_for_vrr(struct drm_crtc *crtc, struct drm_dis mutex_lock(&rockchip_drm_sub_dev_lock); list_for_each_entry(sub_dev, &rockchip_drm_sub_dev_list, list) { - if (sub_dev->connector->state->crtc == crtc) { + if (sub_dev->connector && sub_dev->connector->state->crtc == crtc) { if (sub_dev->update_vfp_for_vrr) sub_dev->update_vfp_for_vrr(sub_dev->connector, mode, vfp); } @@ -432,7 +432,7 @@ int rockchip_drm_get_sub_dev_type(void) mutex_lock(&rockchip_drm_sub_dev_lock); list_for_each_entry(sub_dev, &rockchip_drm_sub_dev_list, list) { - if (sub_dev->connector->encoder) { + if (sub_dev->connector && sub_dev->connector->encoder) { connector_type = sub_dev->connector->connector_type; break; } @@ -451,7 +451,8 @@ u32 rockchip_drm_get_scan_line_time_ns(void) mutex_lock(&rockchip_drm_sub_dev_lock); list_for_each_entry(sub_dev, &rockchip_drm_sub_dev_list, list) { - if (sub_dev->connector->encoder && sub_dev->connector->state->crtc) { + if (sub_dev->connector && sub_dev->connector->encoder && + sub_dev->connector->state->crtc) { mode = &sub_dev->connector->state->crtc->state->adjusted_mode; linedur_ns = div_u64((u64) mode->crtc_htotal * 1000000, mode->crtc_clock); break; @@ -1790,6 +1791,21 @@ static void rockchip_drm_error_event_fini(struct drm_device *drm_dev) device_remove_file(drm_dev->dev, &dev_attr_error_event); } +int rockchip_drm_panel_loader_protect(struct drm_panel *panel, bool on) +{ + struct rockchip_drm_sub_dev *sub_dev; + + if (!panel) + return -EINVAL; + + sub_dev = rockchip_drm_get_sub_dev(panel->dev->of_node); + if (sub_dev && sub_dev->loader_protect) + return sub_dev->loader_protect(sub_dev, on); + + return 0; +} +EXPORT_SYMBOL(rockchip_drm_panel_loader_protect); + static int rockchip_drm_bind(struct device *dev) { struct drm_device *drm_dev; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index 35e56f25dd7e..b166d1f56c50 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -23,8 +24,6 @@ #include -#include "../panel/panel-simple.h" - #include "rockchip_drm_debugfs.h" #define ROCKCHIP_MAX_FB_BUFFER 3 @@ -693,6 +692,7 @@ const char *rockchip_drm_modifier_to_string(uint64_t modifier); void rockchip_drm_reset_iommu_fault_handler_rate_limit(void); void rockchip_drm_send_error_event(struct rockchip_drm_private *priv, enum rockchip_drm_error_event_type event); +int rockchip_drm_panel_loader_protect(struct drm_panel *panel, bool on); __printf(3, 4) void rockchip_drm_dbg(const struct device *dev, diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c index c063514ab517..702f5035ecb7 100644 --- a/drivers/gpu/drm/rockchip/rockchip_lvds.c +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c @@ -436,7 +436,7 @@ static int rockchip_lvds_encoder_loader_protect(struct rockchip_drm_sub_dev *sub struct rockchip_lvds *lvds = container_of(sub_dev, struct rockchip_lvds, sub_dev); if (lvds->panel) - panel_simple_loader_protect(lvds->panel); + rockchip_drm_panel_loader_protect(lvds->panel, on); if (on) { diff --git a/drivers/gpu/drm/rockchip/rockchip_rgb.c b/drivers/gpu/drm/rockchip/rockchip_rgb.c index 806092bcab30..de46f441b323 100644 --- a/drivers/gpu/drm/rockchip/rockchip_rgb.c +++ b/drivers/gpu/drm/rockchip/rockchip_rgb.c @@ -417,7 +417,7 @@ static int rockchip_rgb_encoder_loader_protect(struct rockchip_drm_sub_dev *sub_ } if (rgb->panel) - panel_simple_loader_protect(rgb->panel); + rockchip_drm_panel_loader_protect(rgb->panel, on); if (on) { phy_init(rgb->phy); From a5c5772e79b956ce3de8008f6225ec976ce8d67b Mon Sep 17 00:00:00 2001 From: Weixin Zhou Date: Tue, 24 Jun 2025 14:27:15 +0800 Subject: [PATCH 03/15] MALI: valhall: add gpu mem sysfs entry ls -l sys/class/misc/mali0/device/kprcs/(pid)/ -r--r--r-- 1 root root 4096 2025-06-12 21:59 private_gpu_mem -r--r--r-- 1 root root 4096 2025-06-12 21:59 total_gpu_mem ls -l sys/class/misc/mali0/device/ -r--r--r-- 1 root root 4096 2025-06-12 22:35 private_gpu_mem -r--r--r-- 1 root root 4096 2025-06-12 22:35 total_gpu_mem Signed-off-by: Weixin Zhou Change-Id: Ie14aa324779492bd7983fcf1c94dab86bc066e2c --- .../arm/valhall/context/mali_kbase_context.c | 80 +++++++++++++++++++ .../gpu/arm/valhall/mali_kbase_core_linux.c | 59 ++++++++++++++ drivers/gpu/arm/valhall/mali_kbase_defs.h | 2 + 3 files changed, 141 insertions(+) diff --git a/drivers/gpu/arm/valhall/context/mali_kbase_context.c b/drivers/gpu/arm/valhall/context/mali_kbase_context.c index 34f40073779e..d0283d2817ce 100644 --- a/drivers/gpu/arm/valhall/context/mali_kbase_context.c +++ b/drivers/gpu/arm/valhall/context/mali_kbase_context.c @@ -72,6 +72,74 @@ static struct kbase_process *find_process_node(struct rb_node *node, pid_t tgid) return kprcs; } +static ssize_t kbase_kctx_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) +{ + struct kobj_attribute *kattr = container_of(attr, struct kobj_attribute, attr); + + if (kattr->show) + return kattr->show(kobj, kattr, buf); + + return -EIO; +} + +static ssize_t kbase_total_gpu_mem_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + struct kbase_process *kprcs = container_of(kobj, struct kbase_process, kobj); + + return scnprintf(buf, PAGE_SIZE, "%zu\n", kprcs->total_gpu_pages << PAGE_SHIFT); +} + +static ssize_t kbase_private_gpu_mem_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + struct kbase_process *kprcs = container_of(kobj, struct kbase_process, kobj); + struct kbase_context *tmp_kctx; + size_t total_pages = 0; + + /* Sum up used_pages from all contexts in the process */ + list_for_each_entry(tmp_kctx, &kprcs->kctx_list, kprcs_link) { + total_pages += atomic_read(&tmp_kctx->used_pages); + } + + return scnprintf(buf, PAGE_SIZE, "%zu\n", total_pages << PAGE_SHIFT); +} + +static struct kobj_attribute kbase_total_gpu_mem_attr = { + .attr = { + .name = "total_gpu_mem", + .mode = 0444, + }, + .show = kbase_total_gpu_mem_show, + .store = NULL, +}; + +static struct kobj_attribute kbase_private_gpu_mem_attr = { + .attr = { + .name = "private_gpu_mem", + .mode = 0444, + }, + .show = kbase_private_gpu_mem_show, + .store = NULL, +}; + +static struct attribute *kbase_kctx_attrs[] = { + &kbase_total_gpu_mem_attr.attr, + &kbase_private_gpu_mem_attr.attr, + NULL, +}; + +static const struct attribute_group kbase_kctx_attr_group = { + .attrs = kbase_kctx_attrs, +}; + +static const struct sysfs_ops kbase_kctx_sysfs_ops = { + .show = kbase_kctx_attr_show, +}; + +static const struct kobj_type kbase_kctx_ktype = { + .sysfs_ops = &kbase_kctx_sysfs_ops, + .default_groups = (const struct attribute_group *[]) { &kbase_kctx_attr_group, NULL }, +}; + /** * kbase_insert_kctx_to_process - Initialise kbase process context. * @@ -100,6 +168,8 @@ static int kbase_insert_kctx_to_process(struct kbase_context *kctx) */ if (!kprcs) { struct rb_node **new = &prcs_root->rb_node, *parent = NULL; + char kctx_name[64]; + int ret = 0; kprcs = kzalloc(sizeof(*kprcs), GFP_KERNEL); if (kprcs == NULL) @@ -109,6 +179,15 @@ static int kbase_insert_kctx_to_process(struct kbase_context *kctx) kprcs->dma_buf_root = RB_ROOT; kprcs->total_gpu_pages = 0; + if (unlikely(!scnprintf(kctx_name, 64, "%d", tgid))) + return -ENOMEM; + + ret = kobject_init_and_add(&kprcs->kobj, &kbase_kctx_ktype, kctx->kbdev->kprcs_kobj, kctx_name); + if (ret) { + dev_err(kctx->kbdev->dev, "Failed to create kctx kobject"); + kobject_put(&kprcs->kobj); + } + while (*new) { struct kbase_process *prcs_node; @@ -261,6 +340,7 @@ static void kbase_remove_kctx_from_process(struct kbase_context *kctx) * we can remove it from the process rb_tree. */ if (list_empty(&kprcs->kctx_list)) { + kobject_put(&kprcs->kobj); rb_erase(&kprcs->kprcs_node, &kctx->kbdev->process_root); /* Add checks, so that the terminating process Should not * hold any gpu_memory. diff --git a/drivers/gpu/arm/valhall/mali_kbase_core_linux.c b/drivers/gpu/arm/valhall/mali_kbase_core_linux.c index 081752a4bf60..b7913d22ebbc 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_core_linux.c +++ b/drivers/gpu/arm/valhall/mali_kbase_core_linux.c @@ -2629,6 +2629,56 @@ static ssize_t gpuinfo_show(struct device *dev, struct device_attribute *attr, c } static DEVICE_ATTR_RO(gpuinfo); +/** + * gpumem_private_show - Show callback for the gpumem_private sysfs entry. + * @dev: The device this sysfs file is for. + * @attr: The attributes of the sysfs file. + * @buf: The output buffer to receive the GPU memory information. + * + * This function is called to get the current number of pages used by the GPU. + * The returned value is in bytes. + * + * Return: The number of bytes output to @buf. + */ +static ssize_t private_gpu_mem_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct kbase_device *kbdev; + + CSTD_UNUSED(attr); + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + return scnprintf(buf, PAGE_SIZE, "%llu\n", (u64)atomic_read(&(kbdev->memdev.used_pages)) << PAGE_SHIFT); +} +static DEVICE_ATTR_RO(private_gpu_mem); + +/** + * total_gpu_mem_show - Show callback for the total_gpu_mem sysfs entry. + * @dev: The device this sysfs file is for. + * @attr: The attributes of the sysfs file. + * @buf: The output buffer to receive the GPU memory information. + * + * This function is called to get the total GPU memory including dmabuf memory. + * The returned value is in bytes. + * + * Return: The number of bytes output to @buf. + */ +static ssize_t total_gpu_mem_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct kbase_device *kbdev; + + CSTD_UNUSED(attr); + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + return scnprintf(buf, PAGE_SIZE, "%zu\n", kbdev->total_gpu_pages << PAGE_SHIFT); +} +static DEVICE_ATTR_RO(total_gpu_mem); + /** * dvfs_period_store - Store callback for the dvfs_period sysfs file. * @dev: The device with sysfs file is for @@ -4281,6 +4331,8 @@ static struct attribute *kbase_attrs[] = { &dev_attr_debug_command.attr, #endif &dev_attr_gpuinfo.attr, + &dev_attr_total_gpu_mem.attr, + &dev_attr_private_gpu_mem.attr, &dev_attr_dvfs_period.attr, &dev_attr_pm_poweroff.attr, &dev_attr_reset_timeout.attr, @@ -4328,6 +4380,12 @@ int kbase_sysfs_init(struct kbase_device *kbdev) return err; } + kbdev->kprcs_kobj = kobject_create_and_add("kprcs", &kbdev->dev->kobj); + if (!kbdev->kprcs_kobj) { + dev_err(kbdev->dev, "Creation of kprcs sysfs group failed"); + sysfs_remove_group(&kbdev->dev->kobj, &kbase_scheduling_attr_group); + sysfs_remove_group(&kbdev->dev->kobj, &kbase_attr_group); + } return err; } @@ -4335,6 +4393,7 @@ void kbase_sysfs_term(struct kbase_device *kbdev) { sysfs_remove_group(&kbdev->dev->kobj, &kbase_scheduling_attr_group); sysfs_remove_group(&kbdev->dev->kobj, &kbase_attr_group); + kobject_put(kbdev->kprcs_kobj); put_device(kbdev->dev); } diff --git a/drivers/gpu/arm/valhall/mali_kbase_defs.h b/drivers/gpu/arm/valhall/mali_kbase_defs.h index ccfeacae678b..5edab9b44b9b 100755 --- a/drivers/gpu/arm/valhall/mali_kbase_defs.h +++ b/drivers/gpu/arm/valhall/mali_kbase_defs.h @@ -702,6 +702,7 @@ struct kbase_devfreq_queue_info { * imported multiple times for the process. */ struct kbase_process { + struct kobject kobj; pid_t tgid; size_t total_gpu_pages; struct list_head kctx_list; @@ -1080,6 +1081,7 @@ struct kbase_device { unsigned int nr_regulators; #endif /* CONFIG_REGULATOR */ char devname[DEVNAME_SIZE]; + struct kobject *kprcs_kobj; u32 id; #if !IS_ENABLED(CONFIG_MALI_VALHALL_REAL_HW) From fe81cd9828bc9af844e9ad8a1830c1a16eb96f00 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 4 Jul 2025 10:23:11 +0800 Subject: [PATCH 04/15] input: touchscreen: gt1x: prefix global variables and functions with "gt1x_" update_info -> gt1x_update_info _do_i2c_read -> gt1x_do_i2c_read _do_i2c_write -> gt1x_do_i2c_write Signed-off-by: Tao Huang Change-Id: If8fae2583a0df52f31f22e9844dec7ac3a625517 --- drivers/input/touchscreen/gt1x/gt1x.c | 6 +-- drivers/input/touchscreen/gt1x/gt1x_extents.c | 2 +- drivers/input/touchscreen/gt1x/gt1x_generic.c | 14 +++---- drivers/input/touchscreen/gt1x/gt1x_generic.h | 6 +-- drivers/input/touchscreen/gt1x/gt1x_tools.c | 8 ++-- drivers/input/touchscreen/gt1x/gt1x_update.c | 38 +++++++++---------- 6 files changed, 37 insertions(+), 37 deletions(-) diff --git a/drivers/input/touchscreen/gt1x/gt1x.c b/drivers/input/touchscreen/gt1x/gt1x.c index 8a057ca85637..b34c3fa10be9 100644 --- a/drivers/input/touchscreen/gt1x/gt1x.c +++ b/drivers/input/touchscreen/gt1x/gt1x.c @@ -52,7 +52,7 @@ s32 gt1x_i2c_write(u16 addr, u8 *buffer, s32 len) .flags = 0, .addr = gt1x_i2c_client->addr, }; - return _do_i2c_write(&msg, addr, buffer, len); + return gt1x_do_i2c_write(&msg, addr, buffer, len); } /** @@ -75,7 +75,7 @@ s32 gt1x_i2c_read(u16 addr, u8 *buffer, s32 len) .addr = gt1x_i2c_client->addr, .flags = I2C_M_RD} }; - return _do_i2c_read(msgs, addr, buffer, len); + return gt1x_do_i2c_read(msgs, addr, buffer, len); } static spinlock_t irq_lock; @@ -219,7 +219,7 @@ static void gt1x_ts_work_func(struct work_struct *work) s32 ret = 0; u8 point_data[11] = { 0 }; - if (update_info.status) { + if (gt1x_update_info.status) { GTP_DEBUG("Ignore interrupts during fw update."); return; } diff --git a/drivers/input/touchscreen/gt1x/gt1x_extents.c b/drivers/input/touchscreen/gt1x/gt1x_extents.c index ed087d8f0031..f0e91766372d 100644 --- a/drivers/input/touchscreen/gt1x/gt1x_extents.c +++ b/drivers/input/touchscreen/gt1x/gt1x_extents.c @@ -668,7 +668,7 @@ static long gt1x_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int cnt = 30; /* Blocking when firmwaer updating */ - while (cnt-- && update_info.status) { + while (cnt-- && gt1x_update_info.status) { ssleep(1); } /*GTP_DEBUG("IOCTL CMD:%x", cmd);*/ diff --git a/drivers/input/touchscreen/gt1x/gt1x_generic.c b/drivers/input/touchscreen/gt1x/gt1x_generic.c index abbf764b3fd1..bd31f00811a5 100644 --- a/drivers/input/touchscreen/gt1x/gt1x_generic.c +++ b/drivers/input/touchscreen/gt1x/gt1x_generic.c @@ -260,7 +260,7 @@ static ssize_t gt1x_debug_write_proc(struct file *file, const char *buffer, size } if (strcmp(mode_str, "force_update") == 0) { - update_info.force_update = !!mode; + gt1x_update_info.force_update = !!mode; } return gt1x_debug_proc(buf, count); } @@ -360,7 +360,7 @@ parse_cfg_fail1: } #endif -s32 _do_i2c_read(struct i2c_msg *msgs, u16 addr, u8 *buffer, s32 len) +s32 gt1x_do_i2c_read(struct i2c_msg *msgs, u16 addr, u8 *buffer, s32 len) { s32 ret = -1; s32 pos = 0; @@ -400,7 +400,7 @@ s32 _do_i2c_read(struct i2c_msg *msgs, u16 addr, u8 *buffer, s32 len) return 0; } -s32 _do_i2c_write(struct i2c_msg *msg, u16 addr, u8 *buffer, s32 len) +s32 gt1x_do_i2c_write(struct i2c_msg *msg, u16 addr, u8 *buffer, s32 len) { s32 ret = -1; s32 pos = 0; @@ -519,7 +519,7 @@ s32 gt1x_send_cfg(u8 *config, int cfg_len) s32 retry = 0; u16 checksum = 0; - if (update_info.status) { + if (gt1x_update_info.status) { GTP_DEBUG("Ignore cfg during fw update."); return -1; } @@ -1046,7 +1046,7 @@ void gt1x_power_reset(void) static int rst_flag; s32 i = 0; - if (rst_flag || update_info.status) { + if (rst_flag || gt1x_update_info.status) { return; } GTP_INFO("force_reset_guitar"); @@ -2169,7 +2169,7 @@ int gt1x_suspend(void) u8 buf[1] = { 0 }; #endif - if (update_info.status) { + if (gt1x_update_info.status) { return 0; } #if GTP_SMART_COVER @@ -2238,7 +2238,7 @@ int gt1x_resume(void) { s32 ret = -1; - if (update_info.status) { + if (gt1x_update_info.status) { return 0; } diff --git a/drivers/input/touchscreen/gt1x/gt1x_generic.h b/drivers/input/touchscreen/gt1x/gt1x_generic.h index f73e18283ea7..25c96a449772 100644 --- a/drivers/input/touchscreen/gt1x/gt1x_generic.h +++ b/drivers/input/touchscreen/gt1x/gt1x_generic.h @@ -503,7 +503,7 @@ struct fw_update_info { }; /* Export form gt1x_update.c */ -extern struct fw_update_info update_info; +extern struct fw_update_info gt1x_update_info; extern u8 gt1x_default_FW[]; extern int gt1x_hold_ss51_dsp(void); @@ -527,8 +527,8 @@ extern struct i2c_client *gt1x_i2c_client; extern CHIP_TYPE_T gt1x_chip_type; extern struct gt1x_version_info gt1x_version; -extern s32 _do_i2c_read(struct i2c_msg *msgs, u16 addr, u8 *buffer, s32 len); -extern s32 _do_i2c_write(struct i2c_msg *msg, u16 addr, u8 *buffer, s32 len); +extern s32 gt1x_do_i2c_read(struct i2c_msg *msgs, u16 addr, u8 *buffer, s32 len); +extern s32 gt1x_do_i2c_write(struct i2c_msg *msg, u16 addr, u8 *buffer, s32 len); extern s32 gt1x_i2c_write(u16 addr, u8 *buffer, s32 len); extern s32 gt1x_i2c_read(u16 addr, u8 *buffer, s32 len); extern s32 gt1x_i2c_read_dbl_check(u16 addr, u8 *buffer, s32 len); diff --git a/drivers/input/touchscreen/gt1x/gt1x_tools.c b/drivers/input/touchscreen/gt1x/gt1x_tools.c index 0f38e988615d..8a11266569c1 100644 --- a/drivers/input/touchscreen/gt1x/gt1x_tools.c +++ b/drivers/input/touchscreen/gt1x/gt1x_tools.c @@ -411,10 +411,10 @@ static ssize_t gt1x_tool_read(struct file *filp, char __user *buffer, size_t cou return -1; } else if (4 == cmd_head.wr) { /* read fw update progress */ - buffer[0] = update_info.progress >> 8; - buffer[1] = update_info.progress & 0xff; - buffer[2] = update_info.max_progress >> 8; - buffer[3] = update_info.max_progress & 0xff; + buffer[0] = gt1x_update_info.progress >> 8; + buffer[1] = gt1x_update_info.progress & 0xff; + buffer[2] = gt1x_update_info.max_progress >> 8; + buffer[3] = gt1x_update_info.max_progress & 0xff; *ppos += 4; return 4; } else if (6 == cmd_head.wr) { diff --git a/drivers/input/touchscreen/gt1x/gt1x_update.c b/drivers/input/touchscreen/gt1x/gt1x_update.c index bd8e41b9fdfa..b7c86863e776 100644 --- a/drivers/input/touchscreen/gt1x/gt1x_update.c +++ b/drivers/input/touchscreen/gt1x/gt1x_update.c @@ -130,7 +130,7 @@ struct fw_info { }; #pragma pack() -struct fw_update_info update_info = { +struct fw_update_info gt1x_update_info = { .status = UPDATE_STATUS_IDLE, .progress = 0, .max_progress = 9, @@ -657,16 +657,16 @@ int gt1x_check_firmware(void) u8 *gt1x_get_fw_data(u32 offset, int length) { int ret; - if (update_info.update_type == UPDATE_TYPE_FILE) { - update_info.fw_file->f_op->llseek(update_info.fw_file, offset, SEEK_SET); - ret = update_info.fw_file->f_op->read(update_info.fw_file, (char *)update_info.buffer, length, &update_info.fw_file->f_pos); + if (gt1x_update_info.update_type == UPDATE_TYPE_FILE) { + gt1x_update_info.fw_file->f_op->llseek(gt1x_update_info.fw_file, offset, SEEK_SET); + ret = gt1x_update_info.fw_file->f_op->read(gt1x_update_info.fw_file, (char *) gt1x_update_info.buffer, length, >1x_update_info.fw_file->f_pos); if (ret < 0) { GTP_ERROR("Read data error!"); return NULL; } - return update_info.buffer; + return gt1x_update_info.buffer; } else { - return &update_info.fw_data[offset]; + return >1x_update_info.fw_data[offset]; } } @@ -678,13 +678,13 @@ int gt1x_update_judge(void) struct gt1x_version_info ver_info; struct gt1x_version_info fw_ver_info; - fw_ver_info.mask_id = (update_info.firmware->target_mask_version[0] << 16) - | (update_info.firmware->target_mask_version[1] << 8) - | (update_info.firmware->target_mask_version[2]); - fw_ver_info.patch_id = (update_info.firmware->version[0] << 16) - | (update_info.firmware->version[1] << 8) - | (update_info.firmware->version[2]); - memcpy(fw_ver_info.product_id, update_info.firmware->pid, 4); + fw_ver_info.mask_id = (gt1x_update_info.firmware->target_mask_version[0] << 16) + | (gt1x_update_info.firmware->target_mask_version[1] << 8) + | (gt1x_update_info.firmware->target_mask_version[2]); + fw_ver_info.patch_id = (gt1x_update_info.firmware->version[0] << 16) + | (gt1x_update_info.firmware->version[1] << 8) + | (gt1x_update_info.firmware->version[2]); + memcpy(fw_ver_info.product_id, gt1x_update_info.firmware->pid, 4); fw_ver_info.product_id[4] = 0; /* check fw status reg */ @@ -737,7 +737,7 @@ _reset: return 0; } #if GTP_DEBUG_ON - if (update_info.force_update) { + if (gt1x_update_info.force_update) { GTP_DEBUG("Debug mode, force update fw."); return 0; } @@ -1201,13 +1201,13 @@ int gt1x_error_erase(void) gt1x_reset_guitar(); - fw = gt1x_get_fw_data(update_info.firmware->subsystem[0].offset, - update_info.firmware->subsystem[0].length); + fw = gt1x_get_fw_data(gt1x_update_info.firmware->subsystem[0].offset, + gt1x_update_info.firmware->subsystem[0].length); if (!fw) { GTP_ERROR("get isp fail"); return ERROR_FW; } - ret = gt1x_run_ss51_isp(fw, update_info.firmware->subsystem[0].length); + ret = gt1x_run_ss51_isp(fw, gt1x_update_info.firmware->subsystem[0].length); if (ret) { GTP_ERROR("run isp fail"); return ERROR_PATH; @@ -1311,7 +1311,7 @@ int gt1x_error_erase(void) void gt1x_leave_update_mode(void) { GTP_DEBUG("Leave FW update mode."); - if (update_info.status != UPDATE_STATUS_ABORT) + if (gt1x_update_info.status != UPDATE_STATUS_ABORT) gt1x_reset_guitar(); #if GTP_CHARGER_SWITCH gt1x_charger_switch(SWITCH_ON); @@ -1319,7 +1319,7 @@ void gt1x_leave_update_mode(void) #if GTP_ESD_PROTECT gt1x_esd_switch(SWITCH_ON); #endif - update_info.status = UPDATE_STATUS_IDLE; + gt1x_update_info.status = UPDATE_STATUS_IDLE; gt1x_irq_enable(); } From b789675aded899301e5d3458327f4bbe065342c6 Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Mon, 28 Apr 2025 16:25:19 +0800 Subject: [PATCH 05/15] media: rockchip: isp: support aiisp yuv mode Change-Id: I6aba5461ee1c7c215af648561c9eb8ef6897c2a5 Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/isp/capture.h | 4 + .../media/platform/rockchip/isp/capture_v35.c | 76 ++++++++- drivers/media/platform/rockchip/isp/common.h | 1 + drivers/media/platform/rockchip/isp/dev.h | 1 + .../media/platform/rockchip/isp/isp_params.c | 1 + .../platform/rockchip/isp/isp_params_v35.c | 159 +++++++++++++----- .../platform/rockchip/isp/isp_params_v35.h | 9 + .../media/platform/rockchip/isp/isp_rockit.c | 4 + .../media/platform/rockchip/isp/isp_sditf.c | 2 +- drivers/media/platform/rockchip/isp/rkisp.c | 31 ++-- include/uapi/linux/rk-isp2-config.h | 15 +- 11 files changed, 249 insertions(+), 54 deletions(-) diff --git a/drivers/media/platform/rockchip/isp/capture.h b/drivers/media/platform/rockchip/isp/capture.h index 264320b8e97f..6f908ca3e4b4 100644 --- a/drivers/media/platform/rockchip/isp/capture.h +++ b/drivers/media/platform/rockchip/isp/capture.h @@ -244,6 +244,7 @@ struct streams_ops { int (*set_wrap)(struct rkisp_stream *stream, int line); int (*isp_end)(struct rkisp_stream *stream, u32 irq); int (*switch_grey)(struct rkisp_stream *stream); + void (*push_buf)(struct rkisp_stream *stream); }; struct rockit_isp_ops { @@ -286,12 +287,15 @@ struct rkisp_stream { struct stream_config *config; spinlock_t vbq_lock; struct list_head buf_queue; + struct list_head buf_queue_tmp; struct rkisp_buffer *curr_buf; struct rkisp_buffer *next_buf; struct rkisp_dummy_buffer dummy_buf; struct mutex apilock; struct tasklet_struct buf_done_tasklet; struct list_head buf_done_list; + struct dma_buf *dbuf_pool[VIDEO_MAX_FRAME]; + bool is_rockit_buf; bool streaming; bool stopping; bool frame_end; diff --git a/drivers/media/platform/rockchip/isp/capture_v35.c b/drivers/media/platform/rockchip/isp/capture_v35.c index 62e6d557e221..bd618ec216eb 100644 --- a/drivers/media/platform/rockchip/isp/capture_v35.c +++ b/drivers/media/platform/rockchip/isp/capture_v35.c @@ -12,6 +12,7 @@ #include #include "dev.h" #include "regs.h" +#include "isp_params_v35.h" /* ISP35 * |-->mainpath------------------->ddr @@ -726,12 +727,20 @@ static void update_mi(struct rkisp_stream *stream) struct rkisp_device *dev = stream->ispdev; struct rkisp_dummy_buffer *dummy_buf = &stream->dummy_buf; struct v4l2_pix_format_mplane *out_fmt = &stream->out_fmt; + struct rkisp_isp_params_val_v35 *priv = dev->params_vdev.priv_val; u32 div = stream->out_isp_fmt.fourcc == V4L2_PIX_FMT_UYVY ? 1 : 2; u32 val, reg; if (stream->next_buf) { reg = stream->config->mi.y_base_ad_init; - val = stream->next_buf->buff_addr[RKISP_PLANE_Y]; + if (dev->is_aiisp_yuv && stream->id == RKISP_STREAM_MP) { + val = priv->y_src_idx; + priv->pbuf_y_src = &priv->buf_y_src[val]; + priv->y_src_idx = (val + 1) % priv->y_src_cnt; + val = priv->pbuf_y_src->dma_addr; + } else { + val = stream->next_buf->buff_addr[RKISP_PLANE_Y]; + } rkisp_write(dev, reg, val, false); reg = stream->config->mi.cb_base_ad_init; @@ -803,6 +812,10 @@ static void update_mi(struct rkisp_stream *stream) if (!stream->curr_buf) { stream->curr_buf = stream->next_buf; stream->next_buf = NULL; + if (dev->is_aiisp_yuv && + priv->pbuf_y_src && + stream->id == RKISP_STREAM_MP) + priv->y_src_cur_idx = priv->pbuf_y_src->index; } /* maybe no next buf to preclose mi */ stream->ops->disable_mi(stream); @@ -824,6 +837,10 @@ static void update_mi(struct rkisp_stream *stream) if (!dev->hw_dev->is_single) { stream->curr_buf = stream->next_buf; stream->next_buf = NULL; + if (dev->is_aiisp_yuv && + priv->pbuf_y_src && + stream->id == RKISP_STREAM_MP) + priv->y_src_cur_idx = priv->pbuf_y_src->index; } } else if (dummy_buf->mem_priv) { val = dummy_buf->dma_addr; @@ -922,6 +939,26 @@ static int sp_switch_grey(struct rkisp_stream *stream) return 0; } +static void mp_push_buf(struct rkisp_stream *stream) +{ + unsigned long lock_flags = 0; + struct rkisp_buffer *buf = NULL; + + spin_lock_irqsave(&stream->vbq_lock, lock_flags); + if (!list_empty(&stream->buf_queue_tmp)) { + buf = list_first_entry(&stream->buf_queue_tmp, + struct rkisp_buffer, queue); + list_del(&buf->queue); + } + spin_unlock_irqrestore(&stream->vbq_lock, lock_flags); + if (buf) { + if (buf->vb.vb2_buf.memory) + rkisp_stream_buf_done(stream, buf); + else + rkisp_rockit_buf_done(stream, ROCKIT_DVBM_END, buf); + } +} + static struct streams_ops rkisp_mp_streams_ops = { .config_mi = mp_config_mi, .enable_mi = mp_enable_mi, @@ -933,6 +970,7 @@ static struct streams_ops rkisp_mp_streams_ops = { .frame_start = mi_frame_start, .set_wrap = mp_set_wrap, .switch_grey = mp_switch_grey, + .push_buf = mp_push_buf, }; static struct streams_ops rkisp_sp_streams_ops = { @@ -950,6 +988,7 @@ static struct streams_ops rkisp_sp_streams_ops = { static int mi_frame_start(struct rkisp_stream *stream, u32 irq) { struct rkisp_device *dev = stream->ispdev; + struct rkisp_isp_params_val_v35 *priv = dev->params_vdev.priv_val; unsigned long lock_flags = 0; /* readback start to update stream buf if null */ @@ -977,6 +1016,10 @@ static int mi_frame_start(struct rkisp_stream *stream, u32 irq) if (!stream->ops->is_stream_stopped(stream)) { stream->curr_buf = stream->next_buf; stream->next_buf = NULL; + if (dev->is_aiisp_yuv && + priv->pbuf_y_src && + stream->id == RKISP_STREAM_MP) + priv->y_src_cur_idx = priv->pbuf_y_src->index; if (!list_empty(&stream->buf_queue)) { stream->next_buf = list_first_entry(&stream->buf_queue, struct rkisp_buffer, queue); @@ -1003,6 +1046,7 @@ static int mi_frame_end(struct rkisp_stream *stream, u32 state) { struct rkisp_device *dev = stream->ispdev; struct capture_fmt *isp_fmt = &stream->out_isp_fmt; + struct rkisp_isp_params_val_v35 *priv = dev->params_vdev.priv_val; unsigned long lock_flags = 0; struct rkisp_buffer *buf = NULL; u32 i, seq; @@ -1095,6 +1139,13 @@ static int mi_frame_end(struct rkisp_stream *stream, u32 state) stream->dbg.timestamp = ns; stream->dbg.id = seq; + if (stream->id == RKISP_STREAM_MP && dev->is_aiisp_yuv) { + spin_lock_irqsave(&stream->vbq_lock, lock_flags); + list_add_tail(&buf->queue, &stream->buf_queue_tmp); + spin_unlock_irqrestore(&stream->vbq_lock, lock_flags); + goto end; + } + if (vir->streaming && vir->conn_id == stream->id) { spin_lock_irqsave(&vir->vbq_lock, lock_flags); list_add_tail(&buf->queue, &dev->cap_dev.vir_cpy.queue); @@ -1116,6 +1167,10 @@ end: if (stream->next_buf) { stream->curr_buf = stream->next_buf; stream->next_buf = NULL; + if (dev->is_aiisp_yuv && + priv->pbuf_y_src && + stream->id == RKISP_STREAM_MP) + priv->y_src_cur_idx = priv->pbuf_y_src->index; } if (!list_empty(&stream->buf_queue)) { stream->next_buf = list_first_entry(&stream->buf_queue, @@ -1268,6 +1323,7 @@ static void rkisp_buf_queue(struct vb2_buffer *vb) struct rkisp_device *dev = stream->ispdev; struct v4l2_pix_format_mplane *pixm = &stream->out_fmt; struct capture_fmt *isp_fmt = &stream->out_isp_fmt; + const struct vb2_mem_ops *g_ops = dev->hw_dev->mem_ops; unsigned long lock_flags = 0; struct sg_table *sgt; u32 height, offset; @@ -1308,6 +1364,9 @@ static void rkisp_buf_queue(struct vb2_buffer *vb) v4l2_dbg(2, rkisp_debug, &dev->v4l2_dev, "stream:%d queue buf:0x%x\n", stream->id, ispbuf->buff_addr[0]); + ispbuf->index = vb->index; + if (dev->is_aiisp_yuv && stream->dbuf_pool[vb->index]) + stream->dbuf_pool[vb->index] = g_ops->get_dmabuf(vb, vb->planes[0].mem_priv, O_RDWR); spin_lock_irqsave(&stream->vbq_lock, lock_flags); list_add_tail(&ispbuf->queue, &stream->buf_queue); @@ -1356,7 +1415,14 @@ static void destroy_buf_queue(struct rkisp_stream *stream, { unsigned long lock_flags = 0; struct rkisp_buffer *buf; + int i; + for (i = 0; i < VIDEO_MAX_FRAME && !stream->is_rockit_buf; i++) { + if (stream->dbuf_pool[i]) { + dma_buf_put(stream->dbuf_pool[i]); + stream->dbuf_pool[i] = NULL; + } + } spin_lock_irqsave(&stream->vbq_lock, lock_flags); if (stream->curr_buf) { list_add_tail(&stream->curr_buf->queue, &stream->buf_queue); @@ -1375,6 +1441,13 @@ static void destroy_buf_queue(struct rkisp_stream *stream, if (buf->vb.vb2_buf.memory) vb2_buffer_done(&buf->vb.vb2_buf, state); } + while (!list_empty(&stream->buf_queue_tmp)) { + buf = list_first_entry(&stream->buf_queue_tmp, + struct rkisp_buffer, queue); + list_del(&buf->queue); + if (buf->vb.vb2_buf.memory) + vb2_buffer_done(&buf->vb.vb2_buf, state); + } while (!list_empty(&stream->buf_done_list)) { buf = list_first_entry(&stream->buf_done_list, struct rkisp_buffer, queue); @@ -1635,6 +1708,7 @@ static int rkisp_stream_init(struct rkisp_device *dev, u32 id) vdev = &stream->vnode.vdev; INIT_LIST_HEAD(&stream->buf_queue); + INIT_LIST_HEAD(&stream->buf_queue_tmp); init_waitqueue_head(&stream->done); spin_lock_init(&stream->vbq_lock); stream->linked = true; diff --git a/drivers/media/platform/rockchip/isp/common.h b/drivers/media/platform/rockchip/isp/common.h index 73d7b7858f98..1ef1aaae8a5d 100644 --- a/drivers/media/platform/rockchip/isp/common.h +++ b/drivers/media/platform/rockchip/isp/common.h @@ -123,6 +123,7 @@ struct rkisp_buffer { void *vaddr[VIDEO_MAX_PLANES]; u32 buff_addr[VIDEO_MAX_PLANES]; int dev_id; + int index; void *other; }; diff --git a/drivers/media/platform/rockchip/isp/dev.h b/drivers/media/platform/rockchip/isp/dev.h index 1dafd16c183d..41381783f2a3 100644 --- a/drivers/media/platform/rockchip/isp/dev.h +++ b/drivers/media/platform/rockchip/isp/dev.h @@ -312,6 +312,7 @@ struct rkisp_device { bool is_aiisp_en; bool is_aiisp_upd; bool is_aiisp_sync; + bool is_aiisp_yuv; bool is_frm_rd; bool is_multi_one_sync; bool is_wait_aiq; diff --git a/drivers/media/platform/rockchip/isp/isp_params.c b/drivers/media/platform/rockchip/isp/isp_params.c index 9d7b1d657920..151ac7b3b468 100644 --- a/drivers/media/platform/rockchip/isp/isp_params.c +++ b/drivers/media/platform/rockchip/isp/isp_params.c @@ -311,6 +311,7 @@ static void rkisp_params_vb2_stop_streaming(struct vb2_queue *vq) rkisp_params_stream_stop(params_vdev); params_vdev->is_first_cfg = false; } + dev->is_aiisp_yuv = false; dev->fpn_cfg.en = 0; if (dev->fpn_cfg.buf) { vfree(dev->fpn_cfg.buf); diff --git a/drivers/media/platform/rockchip/isp/isp_params_v35.c b/drivers/media/platform/rockchip/isp/isp_params_v35.c index 177b5f600f34..27ef82b18d1d 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v35.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v35.c @@ -4366,18 +4366,19 @@ isp_rgbir_enable(struct rkisp_isp_params_vdev *params_vdev, bool en, u32 id) isp3_param_write(params_vdev, value, ISP39_RGBIR_CTRL, id); } -static void vpsl_update_buf(struct rkisp_isp_params_vdev *params_vdev) +static void vpsl_update_buf(struct rkisp_isp_params_vdev *params_vdev, + struct rkisp_dummy_buffer *pbuf, bool is_force) { struct rkisp_isp_params_val_v35 *priv = params_vdev->priv_val; struct rkisp_device *dev = params_vdev->dev; u32 i, val, ds_cnt; - if (!priv->pbuf_vpsl) + if (!pbuf) return; - priv->vpsl_cur_idx = priv->pbuf_vpsl->index; + priv->vpsl_idx = pbuf->index; ds_cnt = priv->yraw_sel ? VPSL_YRAW_CHN_MAX / 2 : VPSL_YRAW_CHN_MAX; for (i = 0; i < ds_cnt; i++) { - val = priv->pbuf_vpsl->dma_addr + priv->vpsl_yraw_offs[i]; + val = pbuf->dma_addr + priv->vpsl_yraw_offs[i]; vpsl_write(dev, VPSL_MI_CHN0_WR_BASE + i * 0x100, val, false); val = priv->vpsl_yraw_stride[i]; vpsl_write(dev, VPSL_MI_CHN0_WR_STRIDE + i * 0x100, val, false); @@ -4385,7 +4386,7 @@ static void vpsl_update_buf(struct rkisp_isp_params_vdev *params_vdev) } ds_cnt = priv->yraw_sel ? VPSL_SIG_CHN_MAX - 1 : VPSL_SIG_CHN_MAX; for (i = 0; i < ds_cnt; i++) { - val = priv->pbuf_vpsl->dma_addr + priv->vpsl_sig_offs[i]; + val = pbuf->dma_addr + priv->vpsl_sig_offs[i]; vpsl_write(dev, VPSL_MI_CHN6_WR_BASE + i * 0x100, val, false); val = priv->vpsl_sig_stride[i]; vpsl_write(dev, VPSL_MI_CHN6_WR_STRIDE + i * 0x100, val, false); @@ -4395,7 +4396,7 @@ static void vpsl_update_buf(struct rkisp_isp_params_vdev *params_vdev) vpsl_write(dev, VPSL_MI_IMSC, 0xffffffff, false); val = VPSL_MI_WR_ID_POLL_DIS | VPSL_MI_WR_INIT_OFFSET_EN | VPSL_MI_WR_INIT_BASE_EN; vpsl_write(dev, VPSL_MI_CTRL, val, false); - if (dev->hw_dev->is_single) + if (dev->hw_dev->is_single && is_force) vpsl_write(dev, VPSL_MI_WR_INIT, 0x7ff0, true); } @@ -4474,7 +4475,7 @@ isp_ai_config(struct rkisp_isp_params_vdev *params_vdev, !!arg->aipre_luma2gain_dis << 17; if (params_vdev->is_hdr) val |= ISP35_AIISP_HDR_EN; - if (priv->bay3d_iir_rw_fmt == 2) + if (priv->bay3d_iir_rw_fmt == 2 && params_vdev->dev->is_aiisp_en) val |= ISP35_AIISP_RAW12_MSB; isp3_param_write(params_vdev, val, ISP35_AI_CTRL, id); for (i = 0; i < ISP35_AI_SIGMA_NUM / 2; i++) { @@ -4527,6 +4528,7 @@ isp_ai_enable(struct rkisp_isp_params_vdev *params_vdev, bool en, u32 id) ctrl &= ~(ISP35_AIISP_ST | ISP35_AIPRE_IIR2DDR_EN | ISP35_AIPRE_GIAN2DDR_EN); if (en) { if (priv->buf_aipre_gain[0].mem_priv) { + priv->aipre_gain_idx = 0; priv->aipre_gain_cur_idx = 0; val = priv->buf_aipre_gain[0].dma_addr; isp3_param_write(params_vdev, val, ISP35_AI_PRE_GAIN_WR_BASE, id); @@ -4535,11 +4537,12 @@ isp_ai_enable(struct rkisp_isp_params_vdev *params_vdev, bool en, u32 id) ctrl |= ISP35_AIPRE_GIAN2DDR_EN; } if (priv->buf_vpsl[0].mem_priv) { - vpsl_update_buf(params_vdev); - if (!priv->yraw_sel) - params_vdev->dev->irq_ends_mask |= ISP_FRAME_VPSL; + vpsl_update_buf(params_vdev, priv->pbuf_vpsl, true); + priv->vpsl_cur_idx = priv->vpsl_idx; } - ctrl |= ISP35_AIISP_EN | ISP35_AIPRE_ITS_FORCE_UPD; + ctrl |= ISP35_AIPRE_ITS_FORCE_UPD; + if (params_vdev->dev->is_aiisp_en) + ctrl |= ISP35_AIISP_EN; } else { ctrl &= ~ISP35_AIISP_EN; params_vdev->dev->irq_ends_mask &= ~ISP_FRAME_VPSL; @@ -5305,6 +5308,7 @@ rkisp_params_init_bnr_buf_v35(struct rkisp_isp_params_vdev *params_vdev, INIT_LIST_HEAD(&priv->gain_list); INIT_LIST_HEAD(&priv->vpsl_list); INIT_LIST_HEAD(&priv->aipre_gain_list); + INIT_LIST_HEAD(&priv->y_src_list); iir_rw_fmt = bnrbuf->u.v35.iir_rw_fmt; if (dev->unite_div > ISP_UNITE_DIV1) @@ -5502,7 +5506,53 @@ rkisp_params_init_bnr_buf_v35(struct rkisp_isp_params_vdev *params_vdev, ret = rkisp_alloc_vpsl_buf(params_vdev, bnrbuf); if (ret) goto err_vpsl; + + size = ALIGN(w, 16) * h; + if (dev->unite_div > ISP_UNITE_DIV1) + size *= dev->unite_div; + cnt = bnrbuf->u.v35.y_src.buf_cnt; + if (cnt >= RKISP_BUFFER_MAX) + cnt = RKISP_BUFFER_MAX - 1; + for (i = 0; i < cnt; i++) { + buf = &priv->buf_y_src[i]; + buf->size = size; + buf->is_need_dbuf = true; + buf->is_need_dmafd = true; + ret = rkisp_alloc_buffer(dev, buf); + if (ret) { + dev_err(dev->dev, "alloc y buf%d fail:%d\n", i, ret); + goto err_y_src; + } + if (!i) + priv->pbuf_y_src = buf; + else + list_add_tail(&buf->queue, &priv->y_src_list); + buf->index = i; + bnrbuf->u.v35.y_src.buf_fd[i] = buf->dma_fd; + } + if (cnt && !priv->yraw_sel) + dev->is_aiisp_yuv = true; + priv->y_src_cnt = cnt; + bnrbuf->u.v35.y_src.buf_cnt = cnt; + bnrbuf->u.v35.y_src.buf_size = size; return 0; +err_y_src: + for (i -= 1; i >= 0; i--) { + buf = &priv->buf_y_src[i]; + rkisp_free_buffer(dev, buf); + } + priv->y_src_cnt = 0; + bnrbuf->u.v35.y_src.buf_cnt = 0; + bnrbuf->u.v35.y_src.buf_size = 0; + + i = priv->vpsl_cnt; + for (i -= 1; i >= 0; i--) { + buf = &priv->buf_vpsl[i]; + rkisp_free_buffer(dev, buf); + } + priv->vpsl_cnt = 0; + bnrbuf->u.v35.vpsl.buf_cnt = 0; + bnrbuf->u.v35.vpsl.buf_size = 0; err_vpsl: i = priv->aipre_gain_cnt; err_aipre_gain: @@ -5635,6 +5685,9 @@ rkisp_params_stream_stop_v35(struct rkisp_isp_params_vdev *params_vdev) struct rkisp_device *dev = params_vdev->dev; int i; + for (i = 0; i < priv->y_src_cnt; i++) + rkisp_free_buffer(dev, &priv->buf_y_src[i]); + priv->y_src_cnt = 0; for (i = 0; i < priv->vpsl_cnt; i++) rkisp_free_buffer(dev, &priv->buf_vpsl[i]); priv->vpsl_cnt = 0; @@ -5984,6 +6037,7 @@ rkisp_params_aiisp_event_v35(struct rkisp_isp_params_vdev *params_vdev, u32 irq) { struct rkisp_isp_params_val_v35 *priv = params_vdev->priv_val; struct rkisp_device *dev = params_vdev->dev; + struct rkisp_stream *stream = &dev->cap_dev.stream[RKISP_STREAM_MP]; struct rkisp_dummy_buffer *buf = NULL; struct v4l2_event ev = { 0 }; struct rkisp_aiisp_ev_info *ev_info; @@ -6002,6 +6056,8 @@ rkisp_params_aiisp_event_v35(struct rkisp_isp_params_vdev *params_vdev, u32 irq) ev_info->aiisp_index = -1; ev_info->vpsl_index = -1; ev_info->aipre_gain_index = -1; + ev_info->y_src_index = -1; + ev_info->y_dest_index = -1; val = rkisp_read(dev, ISP39_AIISP_LINE_CNT, false); if (irq & ISP3X_OUT_FRM_QUARTER) { rd_line = ISP39_AIISP_RD_LINECNT(val); @@ -6017,25 +6073,34 @@ rkisp_params_aiisp_event_v35(struct rkisp_isp_params_vdev *params_vdev, u32 irq) list_add_tail(&priv->pbuf_gain_rd->queue, &priv->gain_list); priv->pbuf_gain_rd = NULL; } - if (!priv->yraw_sel) { - buf = priv->pbuf_vpsl; - if (buf) - ev_info->vpsl_index = buf->index; - buf = priv->pbuf_aipre_gain; - if (buf) - ev_info->aipre_gain_index = buf->index; - } spin_unlock_irqrestore(&priv->buf_lock, lock_flags); - v4l2_event_queue(dev->isp_sdev.sd.devnode, &ev); } else { wr_line = ISP39_AIISP_WR_LINECNT(val); ev.id = RKISP_AIISP_WR_LINECNT_ID; ev_info->height = !wr_line ? h : wr_line; rkisp_dmarx_get_frame(dev, &ev_info->sequence, NULL, &ev_info->timestamp, true); + if (dev->aiisp_cfg.wr_mode) { + wr_line += dev->aiisp_cfg.wr_linecnt; + if (wr_line > h) + wr_line = h - 1; + rkisp_write(dev, ISP32_ISP_IRQ_CFG1, wr_line << 16, true); + } + + if (dev->is_aiisp_yuv) { + if (!stream->curr_buf) { + v4l2_dbg(2, rkisp_debug, &dev->v4l2_dev, + "%s seq:%d stream output no buf, drop event\n", + __func__, ev_info->sequence); + return; + } + ev_info->y_dest_index = stream->curr_buf->index; + ev_info->y_src_index = priv->y_src_cur_idx; + } spin_lock_irqsave(&priv->buf_lock, lock_flags); - if (!priv->pbuf_bay3d_iir || !priv->pbuf_vpsl || - !priv->pbuf_gain_wr || !priv->pbuf_aipre_gain) { + if (dev->is_aiisp_en && + (!priv->pbuf_bay3d_iir || !priv->pbuf_vpsl || + !priv->pbuf_gain_wr || !priv->pbuf_aipre_gain)) { if (priv->pbuf_bay3d_iir) { list_add_tail(&priv->pbuf_bay3d_iir->queue, &priv->iir_list); priv->pbuf_bay3d_iir = NULL; @@ -6044,25 +6109,22 @@ rkisp_params_aiisp_event_v35(struct rkisp_isp_params_vdev *params_vdev, u32 irq) list_add_tail(&priv->pbuf_gain_wr->queue, &priv->gain_list); priv->pbuf_gain_wr = NULL; } - if (priv->pbuf_aipre_gain && priv->yraw_sel) { + if (priv->pbuf_aipre_gain) { list_add_tail(&priv->pbuf_aipre_gain->queue, &priv->aipre_gain_list); priv->pbuf_aipre_gain = NULL; } - if (priv->pbuf_vpsl && priv->yraw_sel) { + if (priv->pbuf_vpsl) { list_add_tail(&priv->pbuf_vpsl->queue, &priv->vpsl_list); priv->pbuf_vpsl = NULL; } } - if (priv->yraw_sel) { - buf = priv->pbuf_vpsl; - if (buf) - ev_info->vpsl_index = buf->index; - buf = priv->pbuf_aipre_gain; - if (buf) - ev_info->aipre_gain_index = buf->index; - } - + buf = priv->pbuf_vpsl; + if (buf) + ev_info->vpsl_index = buf->index; + buf = priv->pbuf_aipre_gain; + if (buf) + ev_info->aipre_gain_index = buf->index; buf = priv->pbuf_bay3d_iir; if (buf) ev_info->iir_index = buf->index; @@ -6070,14 +6132,14 @@ rkisp_params_aiisp_event_v35(struct rkisp_isp_params_vdev *params_vdev, u32 irq) if (buf) ev_info->gain_index = buf->index; spin_unlock_irqrestore(&priv->buf_lock, lock_flags); - if (buf) - v4l2_event_queue(dev->isp_sdev.sd.devnode, &ev); } + v4l2_event_queue(dev->isp_sdev.sd.devnode, &ev); v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev, - "%s seq:%d height:%d idx(iir:%d gain:%d vpsl:%d aipre:%d aiisp:%d)\n", + "%s seq:%d height:%d idx(iir:%d gain:%d vpsl:%d aipre:%d aiisp:%d ysrc:%d ydst:%d)\n", ev.id ? "isp_be" : "isp_fe", ev_info->sequence, ev_info->height, ev_info->iir_index, ev_info->gain_index, - ev_info->vpsl_index, ev_info->aipre_gain_index, ev_info->aiisp_index); + ev_info->vpsl_index, ev_info->aipre_gain_index, ev_info->aiisp_index, + ev_info->y_src_index, ev_info->y_dest_index); } static int @@ -6225,6 +6287,7 @@ rkisp_params_isr_v35(struct rkisp_isp_params_vdev *params_vdev, u32 isp_mis) if (!params_vdev->rdbk_times) { if (!dev->is_aiisp_en && priv->bay3d_iir_cnt > 1) { + priv->pbuf_bay3d_iir = &priv->buf_bay3d_iir[priv->bay3d_iir_idx]; priv->bay3d_iir_cur_idx = priv->bay3d_iir_idx; i = (priv->bay3d_iir_idx + 1) % priv->bay3d_iir_cnt; priv->bay3d_iir_idx = i; @@ -6271,6 +6334,21 @@ rkisp_params_isr_v35(struct rkisp_isp_params_vdev *params_vdev, u32 isp_mis) isp3_param_write(params_vdev, val, ISP3X_MI_BAY3D_CUR_WR_BASE, i); } } + if (!dev->is_aiisp_en && priv->aipre_gain_cnt > 1) { + priv->pbuf_aipre_gain = &priv->buf_aipre_gain[priv->aipre_gain_idx]; + priv->aipre_gain_cur_idx = priv->aipre_gain_idx; + i = (priv->aipre_gain_idx + 1) % priv->aipre_gain_cnt; + priv->aipre_gain_idx = i; + + val = priv->buf_aipre_gain[i].dma_addr; + isp3_param_write(params_vdev, val, ISP35_AI_PRE_GAIN_WR_BASE, 0); + } + if (!dev->is_aiisp_en && priv->vpsl_cnt > 1) { + priv->pbuf_vpsl = &priv->buf_vpsl[priv->vpsl_idx]; + priv->vpsl_cur_idx = priv->vpsl_idx; + i = (priv->vpsl_idx + 1) % priv->vpsl_cnt; + vpsl_update_buf(params_vdev, &priv->buf_vpsl[i], false); + } for (i = 0; i < dev->unite_div; i++) { if (params_rec->module_cfg_update & ISP35_MODULE_HDRMGE && (dev->is_aiisp_en || IS_HDR_RDBK(dev->rd_mode))) { @@ -6308,6 +6386,8 @@ void rkisp_params_vpsl_mi_isr_v35(struct rkisp_isp_params_vdev *params_vdev, u32 struct rkisp_device *dev = params_vdev->dev; unsigned long lock_flags = 0; + if (!dev->is_aiisp_en) + return; spin_lock_irqsave(&priv->buf_lock, lock_flags); if (mis_val & VPSL_MI_YRAW_ALL_END) { priv->pbuf_vpsl = NULL; @@ -6315,9 +6395,10 @@ void rkisp_params_vpsl_mi_isr_v35(struct rkisp_isp_params_vdev *params_vdev, u32 priv->pbuf_vpsl = list_first_entry(&priv->vpsl_list, struct rkisp_dummy_buffer, queue); list_del(&priv->pbuf_vpsl->queue); - vpsl_update_buf(params_vdev); + vpsl_update_buf(params_vdev, priv->pbuf_vpsl, true); + priv->vpsl_cur_idx = priv->vpsl_idx; } - if (dev->is_aiisp_sync || !priv->yraw_sel) + if (dev->is_aiisp_sync) rkisp_check_idle(dev, ISP_FRAME_VPSL); } spin_unlock_irqrestore(&priv->buf_lock, lock_flags); diff --git a/drivers/media/platform/rockchip/isp/isp_params_v35.h b/drivers/media/platform/rockchip/isp/isp_params_v35.h index 79d8feaf0b91..0d28402dc02f 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v35.h +++ b/drivers/media/platform/rockchip/isp/isp_params_v35.h @@ -36,18 +36,21 @@ struct rkisp_isp_params_val_v35 { struct rkisp_dummy_buffer buf_aipre_gain[RKISP_BUFFER_MAX]; struct rkisp_dummy_buffer buf_aiisp[RKISP_BUFFER_MAX]; struct rkisp_dummy_buffer buf_vpsl[RKISP_BUFFER_MAX]; + struct rkisp_dummy_buffer buf_y_src[RKISP_BUFFER_MAX]; spinlock_t buf_lock; struct list_head iir_list; struct list_head gain_list; struct list_head aipre_gain_list; struct list_head vpsl_list; + struct list_head y_src_list; struct rkisp_dummy_buffer *pbuf_bay3d_iir; struct rkisp_dummy_buffer *pbuf_gain_wr; struct rkisp_dummy_buffer *pbuf_gain_rd; struct rkisp_dummy_buffer *pbuf_aipre_gain; struct rkisp_dummy_buffer *pbuf_vpsl; struct rkisp_dummy_buffer *pbuf_aiisp; + struct rkisp_dummy_buffer *pbuf_y_src; u32 bay3d_iir_rw_fmt; u32 bay3d_iir_offs; @@ -76,11 +79,17 @@ struct rkisp_isp_params_val_v35 { u32 aipre_gain_stride; int aipre_gain_cnt; + int aipre_gain_idx; int aipre_gain_cur_idx; int vpsl_cnt; + int vpsl_idx; int vpsl_cur_idx; + int y_src_cnt; + int y_src_idx; + int y_src_cur_idx; + u32 vpsl_yraw_offs[VPSL_YRAW_CHN_MAX]; u32 vpsl_yraw_stride[VPSL_YRAW_CHN_MAX]; u32 vpsl_sig_offs[VPSL_SIG_CHN_MAX]; diff --git a/drivers/media/platform/rockchip/isp/isp_rockit.c b/drivers/media/platform/rockchip/isp/isp_rockit.c index fc3375441a7f..9539aed571cb 100644 --- a/drivers/media/platform/rockchip/isp/isp_rockit.c +++ b/drivers/media/platform/rockchip/isp/isp_rockit.c @@ -172,6 +172,9 @@ int rkisp_rockit_buf_queue(struct rockit_cfg *input_rockit_cfg) isprk_buf->sgt = sgt; stream_cfg->rkisp_buff[i] = isprk_buf; stream->buf_cnt++; + isprk_buf->isp_buf.index = i; + stream->dbuf_pool[i] = input_rockit_cfg->buf; + stream->is_rockit_buf = true; } if (ispdev->cap_dev.wrap_line && stream->id == RKISP_STREAM_MP) { @@ -641,6 +644,7 @@ int rkisp_rockit_buf_free(struct rkisp_stream *stream) } } mutex_unlock(&stream_cfg->freebuf_lock); + stream->is_rockit_buf = false; return 0; } diff --git a/drivers/media/platform/rockchip/isp/isp_sditf.c b/drivers/media/platform/rockchip/isp/isp_sditf.c index f38d0b73d12a..3b2fd1088532 100644 --- a/drivers/media/platform/rockchip/isp/isp_sditf.c +++ b/drivers/media/platform/rockchip/isp/isp_sditf.c @@ -159,7 +159,7 @@ void rkisp_sditf_sof(struct rkisp_device *dev, u32 irq) if (!sditf || !sditf->is_on || !sditf->remote_sd) return; info.irq = irq; - rkisp_dmarx_get_frame(dev, &info.seq, NULL, &info.timestamp, true); + rkisp_dmarx_get_frame(dev, &info.seq, NULL, &info.timestamp, !dev->is_aiisp_en); info.unite_index = dev->unite_index; if (dev->isp_ver == ISP_V35) info.grey = !!(rkisp_read(dev, ISP3X_CNR_CTRL, false) & ISP35_CNR_UV_DIS); diff --git a/drivers/media/platform/rockchip/isp/rkisp.c b/drivers/media/platform/rockchip/isp/rkisp.c index 6984ca43282e..8e7ded42ad6d 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.c +++ b/drivers/media/platform/rockchip/isp/rkisp.c @@ -2134,7 +2134,7 @@ static int rkisp_config_isp(struct rkisp_device *dev) rkisp_update_regs(dev, CIF_ISP_OUT_H_SIZE, CIF_ISP_OUT_V_SIZE); } - dev->is_aiisp_upd = dev->is_aiisp_en; + dev->is_aiisp_upd = (dev->is_aiisp_en || dev->aiisp_cfg.wr_linecnt); rkisp_config_cmsk(dev); rkisp_config_aiisp(dev); if (dev->hw_dev->is_single) @@ -3952,21 +3952,20 @@ static void rkisp_config_aiisp(struct rkisp_device *dev) { unsigned long lock_flags = 0; u32 h = dev->isp_sdev.out_crop.height; - u32 wr_line, rd_line, irq, irq_mask, en, en_mask; + u32 wr_line, rd_line, irq_mask, en_mask; + u32 irq = 0, en = 0; spin_lock_irqsave(&dev->aiisp_lock, lock_flags); if (!dev->is_aiisp_upd) goto unlock; dev->is_aiisp_upd = false; - if (dev->is_aiisp_en) { - en = (dev->isp_ver == ISP_V39) ? ISP39_AIISP_EN : ISP35_AIISP_EN; + if (dev->aiisp_cfg.wr_linecnt) irq = ISP39_AIISP_LINECNT_DONE; - if (dev->aiisp_cfg.rd_linecnt) - irq |= ISP3X_OUT_FRM_QUARTER; - } else { - irq = 0; - en = 0; - } + if (dev->aiisp_cfg.rd_linecnt) + irq |= ISP3X_OUT_FRM_QUARTER; + if (dev->is_aiisp_en) + en = (dev->isp_ver == ISP_V39) ? ISP39_AIISP_EN : ISP35_AIISP_EN; + irq_mask = ISP39_AIISP_LINECNT_DONE | ISP3X_OUT_FRM_QUARTER; en_mask = (dev->isp_ver == ISP_V39) ? ISP39_AIISP_EN : ISP35_AIISP_EN; @@ -4087,6 +4086,18 @@ static int rkisp_rdbk_aiisp_event(struct rkisp_device *dev, u32 cmd, void *arg) unsigned long lock_flags = 0; int val, ret = 0; + if (dev->is_aiisp_yuv && cmd == T_CMD_QUEUE) { + struct rkisp_stream *stream = &dev->cap_dev.stream[RKISP_STREAM_MP]; + struct rkisp_aiisp_st *st = arg; + + v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev, + "aiisp yuv input seq:%d idx(vpsl:%d aipre:%d ysrc:%d ydst:%d)\n", + st->sequence, st->vpsl_index, st->aipre_gain_index, + st->y_src_index, st->y_dest_index); + if (stream->ops->push_buf) + stream->ops->push_buf(stream); + } + if (!dev->is_aiisp_en) return -EINVAL; diff --git a/include/uapi/linux/rk-isp2-config.h b/include/uapi/linux/rk-isp2-config.h index 295d2e9283ff..c2ab7d526f51 100644 --- a/include/uapi/linux/rk-isp2-config.h +++ b/include/uapi/linux/rk-isp2-config.h @@ -436,6 +436,9 @@ struct rkisp_aiisp_ev_info { int vpsl_index; int aiisp_index; + + int y_src_index; + int y_dest_index; } __attribute__ ((packed)); struct rkisp_aiisp_st { @@ -449,17 +452,22 @@ struct rkisp_aiisp_st { int aipre_gain_index; int vpsl_index; + + int y_src_index; + int y_dest_index; } __attribute__ ((packed)); /* struct rkisp_aiisp_cfg - * mode: 0: disable aiisp, 1:enable aiisp - * wr_linecnt: aiisp write irq line - * rd_linecnt: aiisp read irq line + * mode: 0:isp whole 1:isp divided into isp_fe and isp_be + * wr_linecnt: btnr iir write irq line + * rd_linecnt: isp_be read irq line + * wr_mode: 0:frame with only one RKISP_AIISP_WR_LINECNT_ID event, else event per wr_linecnt */ struct rkisp_aiisp_cfg { int mode; int wr_linecnt; int rd_linecnt; + int wr_mode; } __attribute__ ((packed)); #define VPSL_YRAW_CHN_MAX 6 @@ -481,6 +489,7 @@ struct rkisp_bnr_buf_info { struct rkisp_buf_info gain; struct rkisp_buf_info aipre_gain; struct rkisp_buf_info vpsl; + struct rkisp_buf_info y_src; __u8 iir_rw_fmt; __u8 gain_mode; __u8 yraw_sel; From ac36b30e88e0818d8f6f0a4058ae58e3bc677d33 Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Sat, 31 May 2025 11:02:16 +0800 Subject: [PATCH 06/15] media: rockchip: isp: aiisp switch for isp35 Change-Id: I57bed352c7e27c3e96710254a7ccbbbba834ff26 Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/isp/dev.h | 4 + .../media/platform/rockchip/isp/isp_params.c | 4 + .../media/platform/rockchip/isp/isp_params.h | 1 + .../platform/rockchip/isp/isp_params_v35.c | 120 ++++++++++++++++-- .../media/platform/rockchip/isp/isp_sditf.c | 3 +- .../platform/rockchip/isp/isp_stats_v35.c | 11 +- drivers/media/platform/rockchip/isp/rkisp.c | 97 +++++++++----- 7 files changed, 197 insertions(+), 43 deletions(-) diff --git a/drivers/media/platform/rockchip/isp/dev.h b/drivers/media/platform/rockchip/isp/dev.h index 41381783f2a3..c641eba2e9ac 100644 --- a/drivers/media/platform/rockchip/isp/dev.h +++ b/drivers/media/platform/rockchip/isp/dev.h @@ -311,6 +311,8 @@ struct rkisp_device { bool is_suspend_one_frame; bool is_aiisp_en; bool is_aiisp_upd; + bool is_aiisp_stopping; + bool is_aiisp_stop; bool is_aiisp_sync; bool is_aiisp_yuv; bool is_frm_rd; @@ -322,6 +324,8 @@ struct rkisp_device { struct rkisp_vicap_sof vicap_sof; u32 hdr_wrap_line; + u32 aiisp_stop_seq; + u8 multi_mode; u8 multi_index; u8 rawaf_irq_cnt; diff --git a/drivers/media/platform/rockchip/isp/isp_params.c b/drivers/media/platform/rockchip/isp/isp_params.c index 151ac7b3b468..efbf9221835a 100644 --- a/drivers/media/platform/rockchip/isp/isp_params.c +++ b/drivers/media/platform/rockchip/isp/isp_params.c @@ -312,6 +312,10 @@ static void rkisp_params_vb2_stop_streaming(struct vb2_queue *vq) params_vdev->is_first_cfg = false; } dev->is_aiisp_yuv = false; + dev->is_aiisp_en = false; + dev->is_aiisp_stop = false; + dev->is_aiisp_stopping = false; + memset(&dev->aiisp_cfg, 0, sizeof(dev->aiisp_cfg)); dev->fpn_cfg.en = 0; if (dev->fpn_cfg.buf) { vfree(dev->fpn_cfg.buf); diff --git a/drivers/media/platform/rockchip/isp/isp_params.h b/drivers/media/platform/rockchip/isp/isp_params.h index cec291be2d3b..ffb76c28a824 100644 --- a/drivers/media/platform/rockchip/isp/isp_params.h +++ b/drivers/media/platform/rockchip/isp/isp_params.h @@ -59,6 +59,7 @@ struct rkisp_isp_params_ops { int (*aiisp_start)(struct rkisp_isp_params_vdev *params_vdev, struct rkisp_aiisp_st *st); int (*get_aiawb_buffd)(struct rkisp_isp_params_vdev *params_vdev, void *arg); void (*vpsl_update_regs)(struct rkisp_isp_params_vdev *params_vdev); + void (*aiisp_switch)(struct rkisp_isp_params_vdev *params_vdev, bool on); }; /* diff --git a/drivers/media/platform/rockchip/isp/isp_params_v35.c b/drivers/media/platform/rockchip/isp/isp_params_v35.c index 27ef82b18d1d..184e4695b50a 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v35.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v35.c @@ -4459,13 +4459,14 @@ isp_ai_config(struct rkisp_isp_params_vdev *params_vdev, u32 i, val; val = isp3_param_read(params_vdev, ISP35_AI_CTRL, id); - val &= (ISP35_AIISP_EN | ISP35_AIPRE_IIR2DDR_EN | ISP35_AIPRE_GIAN2DDR_EN); + val &= (ISP35_AIISP_EN | ISP35_AIPRE_IIR2DDR_EN | ISP35_AIPRE_GIAN2DDR_EN | + ISP35_AIPRE_IIR_EN | ISP35_AIPRE_GAIN_EN); val |= //!!arg->aiisp_raw12_msb << 2 | (arg->aiisp_gain_mode & 0x3) << 4 | !!arg->aiisp_curve_en << 6 | - !!arg->aipre_iir_en << 8 | + //!!arg->aipre_iir_en << 8 | //!!arg->aipre_iir2ddr_en << 9 | - !!arg->aipre_gain_en << 10 | + //!!arg->aipre_gain_en << 10 | //!!arg->aipre_gain2ddr_en << 11 | !!arg->aipre_yraw_sel << 12 | !!arg->aipre_nl_ddr_mode << 13 | @@ -4525,7 +4526,8 @@ isp_ai_enable(struct rkisp_isp_params_vdev *params_vdev, bool en, u32 id) if (en == !!(ctrl & ISP35_MODULE_EN)) return; - ctrl &= ~(ISP35_AIISP_ST | ISP35_AIPRE_IIR2DDR_EN | ISP35_AIPRE_GIAN2DDR_EN); + ctrl &= ~(ISP35_AIISP_ST | ISP35_AIPRE_IIR2DDR_EN | ISP35_AIPRE_GIAN2DDR_EN | + ISP35_AIPRE_IIR_EN | ISP35_AIPRE_GAIN_EN); if (en) { if (priv->buf_aipre_gain[0].mem_priv) { priv->aipre_gain_idx = 0; @@ -4534,15 +4536,21 @@ isp_ai_enable(struct rkisp_isp_params_vdev *params_vdev, bool en, u32 id) isp3_param_write(params_vdev, val, ISP35_AI_PRE_GAIN_WR_BASE, id); val = priv->aipre_gain_stride; isp3_param_write(params_vdev, val, ISP35_AI_PRE_GAIN_WR_STRIDE, id); - ctrl |= ISP35_AIPRE_GIAN2DDR_EN; + ctrl |= ISP35_AIPRE_GIAN2DDR_EN | ISP35_AIPRE_GAIN_EN; } if (priv->buf_vpsl[0].mem_priv) { + if (priv->yraw_sel) + ctrl |= ISP35_AIPRE_IIR_EN; vpsl_update_buf(params_vdev, priv->pbuf_vpsl, true); priv->vpsl_cur_idx = priv->vpsl_idx; + if (params_vdev->dev->is_aiisp_sync) + params_vdev->dev->irq_ends_mask |= ISP_FRAME_VPSL; } ctrl |= ISP35_AIPRE_ITS_FORCE_UPD; if (params_vdev->dev->is_aiisp_en) ctrl |= ISP35_AIISP_EN; + else if (params_vdev->dev->is_aiisp_stop) + ctrl &= ~(ISP35_AIPRE_GIAN2DDR_EN | ISP35_AIPRE_GAIN_EN | ISP35_AIPRE_IIR_EN); } else { ctrl &= ~ISP35_AIISP_EN; params_vdev->dev->irq_ends_mask &= ~ISP_FRAME_VPSL; @@ -5991,6 +5999,7 @@ rkisp_params_aiisp_update_buf(struct rkisp_isp_params_vdev *params_vdev) val = priv->pbuf_aipre_gain->dma_addr; isp3_param_write(params_vdev, val, ISP35_AI_PRE_GAIN_WR_BASE, 0); + priv->aipre_gain_cur_idx = priv->pbuf_aipre_gain->index; if (params_vdev->dev->hw_dev->is_single) { val = isp3_param_read(params_vdev, ISP35_AI_CTRL, 0); @@ -6273,6 +6282,100 @@ rkisp_vpsl_update_regs_v35(struct rkisp_isp_params_vdev *params_vdev) writel(VPSL_MI_FORCE_UPD, base + VPSL_MI_WR_INIT); } +static void +rkisp_params_aiisp_switch_v35(struct rkisp_isp_params_vdev *params_vdev, bool on) +{ + struct rkisp_device *dev = params_vdev->dev; + struct rkisp_isp_stats_vdev *stats_vdev = &dev->stats_vdev; + struct rkisp_isp_params_val_v35 *priv = params_vdev->priv_val; + struct isp35_isp_params_cfg *params; + struct rkisp_buffer *params_buf; + unsigned long flags = 0; + u32 val; + + v4l2_dbg(2, rkisp_debug, &dev->v4l2_dev, + "%s on:%d\n", __func__, on); + if (!on) { + spin_lock_irqsave(¶ms_vdev->config_lock, flags); + while (!list_empty(¶ms_vdev->params_be)) { + params_buf = list_first_entry(¶ms_vdev->params_be, struct rkisp_buffer, queue); + list_del(¶ms_buf->queue); + params = params_buf->vaddr[0]; + __isp_isr_meas_config(params_vdev, params, RKISP_PARAMS_LAT, 0); + __isp_isr_other_config(params_vdev, params, RKISP_PARAMS_LAT, 0); + __isp_isr_other_en(params_vdev, params, RKISP_PARAMS_LAT, 0); + __isp_isr_meas_en(params_vdev, params, RKISP_PARAMS_LAT, 0); + params->module_cfg_update = 0; + vb2_buffer_done(¶ms_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); + } + spin_unlock_irqrestore(¶ms_vdev->config_lock, flags); + + val = rkisp_read(dev, ISP35_AI_CTRL, false); + val &= ~(ISP35_AIISP_ST | ISP35_AIISP_EN | + ISP35_AIPRE_IIR_EN | ISP35_AIPRE_GAIN_EN | + ISP35_AIPRE_IIR2DDR_EN | ISP35_AIPRE_GIAN2DDR_EN); + val |= ISP35_AIPRE_ITS_FORCE_UPD; + rkisp_write(dev, ISP35_AI_CTRL, val, false); + val &= ~ISP35_AIPRE_ITS_FORCE_UPD; + rkisp_write(dev, ISP35_AI_CTRL, val, false); + + val = rkisp_read(dev, ISP3X_MI_BAY3D_IIR_RD_BASE_SHD, true); + rkisp_write(dev, ISP3X_MI_BAY3D_IIR_WR_BASE, val, false); + if (dev->hw_dev->is_single) { + val = ISP3X_BAY3D_IIRSELF_UPD | ISP3X_BAY3D_RDSELF_UPD | + ISP3X_GAINSELF_UPD; + rkisp_set_bits(dev, MI_WR_CTRL2, 0, val, false); + } + + rkisp_stats_first_ddr_config(stats_vdev); + rkisp_stats_next_ddr_config(stats_vdev); + + val = rkisp_read(dev, ISP3X_ISP_CTRL1, false); + val &= ~ISP35_BAYER_UPD_FE_EN; + rkisp_write(dev, ISP3X_ISP_CTRL1, val, false); + + val = ISP39_AIISP_LINECNT_DONE | ISP3X_OUT_FRM_QUARTER | ISP3X_BAY3D_FRM_END; + rkisp_clear_bits(dev, CIF_ISP_IMSC, val, false); + } else { + val = rkisp_read(dev, ISP3X_ISP_CTRL1, false); + val |= ISP35_BAYER_PAT_FE(params_vdev->raw_type) | ISP35_BAYER_UPD_FE_EN; + rkisp_write(dev, ISP3X_ISP_CTRL1, val, false); + + if (priv->pbuf_bay3d_iir) { + val = priv->pbuf_bay3d_iir->dma_addr; + rkisp_write(dev, ISP3X_MI_BAY3D_IIR_WR_BASE, val, false); + if (dev->hw_dev->is_single) { + val = ISP3X_BAY3D_IIRSELF_UPD | ISP3X_BAY3D_RDSELF_UPD | + ISP3X_GAINSELF_UPD; + rkisp_set_bits(dev, MI_WR_CTRL2, 0, val, false); + } + } + + spin_lock_irqsave(&stats_vdev->rd_lock, flags); + if (stats_vdev->cur_buf) { + list_add_tail(&stats_vdev->cur_buf->queue, &stats_vdev->stat); + stats_vdev->cur_buf = NULL; + } + if (stats_vdev->nxt_buf) { + list_add_tail(&stats_vdev->nxt_buf->queue, &stats_vdev->stat); + stats_vdev->nxt_buf = NULL; + } + spin_unlock_irqrestore(&stats_vdev->rd_lock, flags); + rkisp_stats_first_ddr_config(stats_vdev); + + val = rkisp_read(dev, ISP35_AI_CTRL, false); + val &= ~ISP35_AIISP_ST; + val |= ISP35_AIPRE_GIAN2DDR_EN | ISP35_AIISP_EN | + ISP35_AIPRE_IIR_EN | ISP35_AIPRE_GAIN_EN | + ISP35_AIISP_RAW12_MSB | ISP35_AIPRE_ITS_FORCE_UPD; + rkisp_write(dev, ISP35_AI_CTRL, val, false); + val &= ~ISP35_AIPRE_ITS_FORCE_UPD; + rkisp_write(dev, ISP35_AI_CTRL, val, false); + + params_vdev->cur_fe_frame_id = params_vdev->cur_frame_id; + } +} + static void rkisp_params_isr_v35(struct rkisp_isp_params_vdev *params_vdev, u32 isp_mis) { @@ -6286,7 +6389,7 @@ rkisp_params_isr_v35(struct rkisp_isp_params_vdev *params_vdev, u32 isp_mis) params_vdev->rdbk_times--; if (!params_vdev->rdbk_times) { - if (!dev->is_aiisp_en && priv->bay3d_iir_cnt > 1) { + if (!dev->is_aiisp_en && !dev->is_aiisp_stop && priv->bay3d_iir_cnt > 1) { priv->pbuf_bay3d_iir = &priv->buf_bay3d_iir[priv->bay3d_iir_idx]; priv->bay3d_iir_cur_idx = priv->bay3d_iir_idx; i = (priv->bay3d_iir_idx + 1) % priv->bay3d_iir_cnt; @@ -6334,7 +6437,7 @@ rkisp_params_isr_v35(struct rkisp_isp_params_vdev *params_vdev, u32 isp_mis) isp3_param_write(params_vdev, val, ISP3X_MI_BAY3D_CUR_WR_BASE, i); } } - if (!dev->is_aiisp_en && priv->aipre_gain_cnt > 1) { + if (!dev->is_aiisp_en && !dev->is_aiisp_stop && priv->aipre_gain_cnt > 1) { priv->pbuf_aipre_gain = &priv->buf_aipre_gain[priv->aipre_gain_idx]; priv->aipre_gain_cur_idx = priv->aipre_gain_idx; i = (priv->aipre_gain_idx + 1) % priv->aipre_gain_cnt; @@ -6343,7 +6446,7 @@ rkisp_params_isr_v35(struct rkisp_isp_params_vdev *params_vdev, u32 isp_mis) val = priv->buf_aipre_gain[i].dma_addr; isp3_param_write(params_vdev, val, ISP35_AI_PRE_GAIN_WR_BASE, 0); } - if (!dev->is_aiisp_en && priv->vpsl_cnt > 1) { + if (!dev->is_aiisp_en && !dev->is_aiisp_stop && priv->vpsl_cnt > 1) { priv->pbuf_vpsl = &priv->buf_vpsl[priv->vpsl_idx]; priv->vpsl_cur_idx = priv->vpsl_idx; i = (priv->vpsl_idx + 1) % priv->vpsl_cnt; @@ -6425,6 +6528,7 @@ static struct rkisp_isp_params_ops rkisp_isp_params_ops_tbl = { .aiisp_event = rkisp_params_aiisp_event_v35, .aiisp_start = rkisp_params_aiisp_start_v35, .vpsl_update_regs = rkisp_vpsl_update_regs_v35, + .aiisp_switch = rkisp_params_aiisp_switch_v35, }; int rkisp_init_params_vdev_v35(struct rkisp_isp_params_vdev *params_vdev) diff --git a/drivers/media/platform/rockchip/isp/isp_sditf.c b/drivers/media/platform/rockchip/isp/isp_sditf.c index 3b2fd1088532..14315191f569 100644 --- a/drivers/media/platform/rockchip/isp/isp_sditf.c +++ b/drivers/media/platform/rockchip/isp/isp_sditf.c @@ -64,7 +64,8 @@ static int rkisp_sditf_s_stream(struct v4l2_subdev *sd, int on) if (ret < 0) goto pipe_close; sditf->is_on = true; - dev->irq_ends_mask |= ISP_FRAME_VPSS; + if (!dev->is_aiisp_sync) + dev->irq_ends_mask |= ISP_FRAME_VPSS; goto unlock; } sditf->is_on = false; diff --git a/drivers/media/platform/rockchip/isp/isp_stats_v35.c b/drivers/media/platform/rockchip/isp/isp_stats_v35.c index e3ef0c607b74..29036ccb311d 100644 --- a/drivers/media/platform/rockchip/isp/isp_stats_v35.c +++ b/drivers/media/platform/rockchip/isp/isp_stats_v35.c @@ -812,7 +812,9 @@ rkisp_stats_first_ddr_config_v35(struct rkisp_isp_stats_vdev *stats_vdev) rkisp_get_stat_size_v35(stats_vdev, &size); stats_vdev->stats_buf[0].is_need_vaddr = true; stats_vdev->stats_buf[0].size = size; - if (rkisp_alloc_buffer(dev, &stats_vdev->stats_buf[0])) + if (!stats_vdev->stats_buf[0].mem_priv) + rkisp_alloc_buffer(dev, &stats_vdev->stats_buf[0]); + if (!stats_vdev->stats_buf[0].vaddr) v4l2_warn(&dev->v4l2_dev, "stats alloc buf fail\n"); else memset(stats_vdev->stats_buf[0].vaddr, 0, size); @@ -823,12 +825,14 @@ rkisp_stats_first_ddr_config_v35(struct rkisp_isp_stats_vdev *stats_vdev) if (dev->hw_dev->is_single) rkisp_unite_set_bits(dev, ISP3X_SWS_CFG, 0, ISP3X_3A_DDR_WRITE_EN, false); val = rkisp_read(dev, ISP39_W3A_CTRL0, false); + val &= ~(ISP39_W3A_AUTO_CLR_EN | ISP35_W3A_FORCE_UPD_F); val |= ISP39_W3A_EN | ISP39_W3A_FORCE_UPD; if (!dev->is_aiisp_en) val |= ISP39_W3A_AUTO_CLR_EN; else val |= ISP35_W3A_FORCE_UPD_F; - if (pdaf_vdev && pdaf_vdev->streaming) { + if (pdaf_vdev && pdaf_vdev->streaming && + !(dev->isp_state & ISP_START)) { val |= ISP39_W3A_PDAF_EN; rkisp_pdaf_update_buf(dev); if (pdaf_vdev->next_buf) { @@ -857,7 +861,8 @@ rkisp_stats_next_ddr_config_v35(struct rkisp_isp_stats_vdev *stats_vdev) if (hw->is_single) { if (!dev->is_aiisp_en) rkisp_stats_update_buf(stats_vdev); - if (pdaf_vdev && pdaf_vdev->streaming) + if (pdaf_vdev && pdaf_vdev->streaming && + !(dev->isp_state & ISP_START)) rkisp_pdaf_update_buf(dev); } } diff --git a/drivers/media/platform/rockchip/isp/rkisp.c b/drivers/media/platform/rockchip/isp/rkisp.c index 8e7ded42ad6d..0217f8ebd5c6 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.c +++ b/drivers/media/platform/rockchip/isp/rkisp.c @@ -758,6 +758,8 @@ static void rkisp_check_mi_ends_mask(struct rkisp_device *dev) dev->irq_ends_mask |= ISP_FRAME_LDC; else dev->irq_ends_mask &= ~ISP_FRAME_LDC; + if (dev->sditf_dev && dev->sditf_dev->is_on) + dev->irq_ends_mask |= ISP_FRAME_VPSS; } /* @@ -834,7 +836,6 @@ void rkisp_trigger_read_back(struct rkisp_device *dev, u8 dma2frm, u32 mode, boo dev->isp_sdev.quantization); rkisp_params_cfg(params_vdev, cur_frame_id, RKISP_PARAMS_IMD); rkisp_config_cmsk(dev); - rkisp_config_aiisp(dev); if (!dev->is_aiisp_en || (dev->is_aiisp_sync && !dev->is_first_frame)) rkisp_stream_frame_start(dev, 0); @@ -1358,11 +1359,13 @@ static void rkisp_frame_end_idle(struct rkisp_device *dev) if (!(dev->irq_ends_mask & val)) { u32 state = dev->isp_state; struct rkisp_stream *s; + bool sditf_off = true; if (dev->sditf_dev && !dev->sditf_dev->is_on) dev->isp_state = ISP_STOP; - - for (val = 0; val < RKISP_STREAM_VIR; val++) { + else if (dev->sditf_dev && dev->sditf_dev->is_on) + sditf_off = false; + for (val = 0; val < RKISP_STREAM_VIR && sditf_off; val++) { s = &dev->cap_dev.stream[val]; dev->isp_state = ISP_STOP; if (s->streaming) { @@ -1427,6 +1430,15 @@ static void rkisp_back_end_idle(struct rkisp_device *dev) rkisp_rdbk_aiisp_event(dev, T_CMD_END, NULL); if (dev->isp_state == ISP_STOP && dev->hw_dev->is_idle) wake_up(&dev->sync_onoff); + if (dev->is_aiisp_stopping && dev->hw_dev->is_be_idle && + dev->aiisp_stop_seq == dev->dmarx_dev.cur_be_frame.id) { + dev->is_aiisp_en = false; + if (dev->params_vdev.ops->aiisp_switch) + dev->params_vdev.ops->aiisp_switch(&dev->params_vdev, false); + dev->is_aiisp_stopping = false; + dev->is_aiisp_stop = true; + rkisp_vicap_hw_link(dev, true); + } } void rkisp_check_idle(struct rkisp_device *dev, u32 irq) @@ -1463,15 +1475,19 @@ void rkisp_check_idle(struct rkisp_device *dev, u32 irq) spin_unlock_irqrestore(&hw->rdbk_lock, lock_flags); if (isp_front_end) { - if (hw->is_single && !IS_HDR_RDBK(dev->rd_mode)) + if (hw->is_single && !IS_HDR_RDBK(dev->rd_mode)) { + rkisp_config_aiisp(dev); return; + } rkisp_front_end_idle(dev); } if (isp_back_end) rkisp_back_end_idle(dev); if (isp_frame_end) { - if (hw->is_single && !IS_HDR_RDBK(dev->rd_mode)) + if (hw->is_single && !IS_HDR_RDBK(dev->rd_mode)) { + rkisp_config_aiisp(dev); return; + } rkisp_frame_end_idle(dev); } } @@ -1972,7 +1988,7 @@ static int rkisp_config_isp(struct rkisp_device *dev) u32 acq_mult = 0; u32 acq_prop = 0; u32 extend_line = 0; - u32 width, height, val; + u32 width, height; sensor = dev->active_sensor; in_fmt = &dev->isp_sdev.in_fmt; @@ -2077,31 +2093,19 @@ static int rkisp_config_isp(struct rkisp_device *dev) /* Acquisition Size */ rkisp_unite_write(dev, CIF_ISP_ACQ_H_OFFS, acq_mult * in_crop->left, false); rkisp_unite_write(dev, CIF_ISP_ACQ_V_OFFS, in_crop->top, false); - if (dev->isp_ver == ISP_V35 && dev->is_aiisp_en) - val = (acq_mult * width) | (acq_mult * width) << 16; - else - val = acq_mult * width; - rkisp_unite_write(dev, CIF_ISP_ACQ_H_SIZE, val, false); + rkisp_unite_write(dev, CIF_ISP_ACQ_H_SIZE, acq_mult * width, false); /* ISP Out Area differ with ACQ is only FIFO, so don't crop in this */ rkisp_unite_write(dev, CIF_ISP_OUT_H_OFFS, 0, true); rkisp_unite_write(dev, CIF_ISP_OUT_V_OFFS, 0, true); - if (dev->isp_ver == ISP_V35 && dev->is_aiisp_en) - val = width | width << 16; - else - val = width; - rkisp_unite_write(dev, CIF_ISP_OUT_H_SIZE, val, false); + rkisp_unite_write(dev, CIF_ISP_OUT_H_SIZE, width, false); if (dev->cap_dev.stream[RKISP_STREAM_SP].interlaced) { rkisp_unite_write(dev, CIF_ISP_ACQ_V_SIZE, height / 2, false); rkisp_unite_write(dev, CIF_ISP_OUT_V_SIZE, height / 2, false); } else { - if (dev->isp_ver == ISP_V35 && dev->is_aiisp_en) - val = (height + extend_line) | (height + extend_line) << 16; - else - val = height + extend_line; - rkisp_unite_write(dev, CIF_ISP_ACQ_V_SIZE, val, false); - rkisp_unite_write(dev, CIF_ISP_OUT_V_SIZE, val, false); + rkisp_unite_write(dev, CIF_ISP_ACQ_V_SIZE, height + extend_line, false); + rkisp_unite_write(dev, CIF_ISP_OUT_V_SIZE, height + extend_line, false); } /* interrupt mask */ @@ -3963,11 +3967,37 @@ static void rkisp_config_aiisp(struct rkisp_device *dev) irq = ISP39_AIISP_LINECNT_DONE; if (dev->aiisp_cfg.rd_linecnt) irq |= ISP3X_OUT_FRM_QUARTER; - if (dev->is_aiisp_en) - en = (dev->isp_ver == ISP_V39) ? ISP39_AIISP_EN : ISP35_AIISP_EN; - irq_mask = ISP39_AIISP_LINECNT_DONE | ISP3X_OUT_FRM_QUARTER; - en_mask = (dev->isp_ver == ISP_V39) ? ISP39_AIISP_EN : ISP35_AIISP_EN; + if (!(dev->isp_state & ISP_START) && dev->is_aiisp_stop) + goto unlock; + + if (dev->is_aiisp_en && !dev->aiisp_cfg.mode) { + if (!IS_HDR_RDBK(dev->rd_mode)) { + dev->is_aiisp_stopping = true; + dev->aiisp_stop_seq = dev->dmarx_dev.cur_frame.id; + goto unlock; + } else { + dev->is_aiisp_en = false; + irq = 0; + } + } else if (!dev->is_aiisp_en && dev->aiisp_cfg.mode) { + dev->is_aiisp_en = true; + dev->is_aiisp_stop = false; + if (dev->params_vdev.ops->aiisp_switch) + dev->params_vdev.ops->aiisp_switch(&dev->params_vdev, true); + } + + if (dev->is_aiisp_en) { + irq |= ISP3X_BAY3D_FRM_END; + if (!dev->is_aiisp_sync) + dev->irq_f_ends_mask |= ISP_FRAME_BNR; + en = (dev->isp_ver == ISP_V39) ? ISP39_AIISP_EN : ISP35_AIISP_EN; + } + irq_mask = ISP39_AIISP_LINECNT_DONE | ISP3X_OUT_FRM_QUARTER | ISP3X_BAY3D_FRM_END; + if (dev->isp_ver == ISP_V39) + en_mask = ISP39_AIISP_EN; + else + en_mask = ISP35_AIISP_EN | ISP35_AIISP_ST; if (dev->aiisp_cfg.rd_linecnt >= h) rd_line = h - 1; @@ -3981,6 +4011,7 @@ static void rkisp_config_aiisp(struct rkisp_device *dev) rkisp_write(dev, ISP32_ISP_IRQ_CFG0, rd_line, false); rkisp_write(dev, ISP32_ISP_IRQ_CFG1, wr_line, false); rkisp_write(dev, ISP39_SLICE_ST_CTRL, 0, false); + rkisp_write(dev, CIF_ISP_ICR, irq_mask, false); rkisp_set_bits(dev, CIF_ISP_IMSC, irq_mask, irq, false); if (dev->isp_ver == ISP_V39) rkisp_set_bits(dev, ISP3X_MI_RD_CTRL2, en_mask, en, false); @@ -3988,6 +4019,8 @@ static void rkisp_config_aiisp(struct rkisp_device *dev) rkisp_set_bits(dev, ISP35_AI_CTRL, en_mask, en, false); unlock: spin_unlock_irqrestore(&dev->aiisp_lock, lock_flags); + if (dev->is_aiisp_stopping) + rkisp_vicap_hw_link(dev, false); } static int rkisp_set_aiisp_linecnt(struct rkisp_device *dev, @@ -3998,7 +4031,11 @@ static int rkisp_set_aiisp_linecnt(struct rkisp_device *dev, if (dev->isp_ver != ISP_V39 && dev->isp_ver != ISP_V35) return -EINVAL; spin_lock_irqsave(&dev->aiisp_lock, lock_flags); - dev->is_aiisp_en = !!cfg->mode; + if (!(dev->isp_state & ISP_START)) { + if (!cfg->mode && cfg->wr_linecnt && cfg->rd_linecnt) + dev->is_aiisp_stop = true; + dev->is_aiisp_en = !!cfg->mode; + } dev->is_aiisp_upd = true; dev->aiisp_cfg = *cfg; spin_unlock_irqrestore(&dev->aiisp_lock, lock_flags); @@ -4273,7 +4310,7 @@ static int rkisp_vicap_sof(struct rkisp_device *dev, struct rkisp_vicap_sof *sof spin_lock_irqsave(&dev->rdbk_lock, flag); if (!IS_HDR_RDBK(dev->rd_mode) && sof->sequence - dev->dmarx_dev.cur_frame.id > 1) { - v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev, + v4l2_dbg(4, rkisp_debug, &dev->v4l2_dev, "vicap sof %d, isp sof %d\n", sof->sequence, dev->dmarx_dev.cur_frame.id); dev->dmarx_dev.cur_frame.id = sof->sequence - 1; @@ -5266,10 +5303,8 @@ vs_skip: if ((isp_mis & CIF_ISP_FRAME) && dev->stats_vdev.rdbk_mode) rkisp_stats_rdbk_enable(&dev->stats_vdev, false); - if (!IS_HDR_RDBK(dev->hdr.op_mode)) { - rkisp_config_aiisp(dev); + if (!IS_HDR_RDBK(dev->hdr.op_mode)) rkisp_config_cmsk(dev); - } } if (isp_mis & CIF_ISP_FRAME) { From e78f73a9b5a577340aff9736a0ec050491224e3a Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Fri, 6 Jun 2025 11:01:47 +0800 Subject: [PATCH 07/15] media: rockchip: isp: aiisp switch for offline mode Change-Id: I4e72621acf57d4497cb53b905e9ec75a23f558cd Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/isp/dev.c | 3 +- .../platform/rockchip/isp/isp_params_v35.c | 22 ++++++++-- drivers/media/platform/rockchip/isp/rkisp.c | 41 ++++++++++++++----- 3 files changed, 51 insertions(+), 15 deletions(-) diff --git a/drivers/media/platform/rockchip/isp/dev.c b/drivers/media/platform/rockchip/isp/dev.c index 0d4ac1afe006..3a976fad466a 100644 --- a/drivers/media/platform/rockchip/isp/dev.c +++ b/drivers/media/platform/rockchip/isp/dev.c @@ -351,8 +351,7 @@ static int rkisp_pipeline_open(struct rkisp_pipeline *p, rkisp_csi_config_patch(dev, false); dev->is_aiisp_sync = false; if (dev->is_aiisp_en && - ((dev->isp_ver == ISP_V35 && !hw->is_single) || - (dev->isp_ver == ISP_V39 && (dev->isp_inp & INP_RAWRD2 || dev->is_rdbk_auto)))) + (!hw->is_single || IS_HDR_RDBK(dev->rd_mode))) dev->is_aiisp_sync = true; return 0; err: diff --git a/drivers/media/platform/rockchip/isp/isp_params_v35.c b/drivers/media/platform/rockchip/isp/isp_params_v35.c index 184e4695b50a..9b2a84b44c8e 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v35.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v35.c @@ -6053,6 +6053,7 @@ rkisp_params_aiisp_event_v35(struct rkisp_isp_params_vdev *params_vdev, u32 irq) unsigned long lock_flags = 0; u32 h = dev->isp_sdev.out_crop.height; u32 val, wr_line, rd_line; + bool is_event_queue = true; if (sizeof(*ev_info) > sizeof(ev.u)) { v4l2_err(&dev->v4l2_dev, "aiisp_ev_info too large\n"); @@ -6126,6 +6127,7 @@ rkisp_params_aiisp_event_v35(struct rkisp_isp_params_vdev *params_vdev, u32 irq) list_add_tail(&priv->pbuf_vpsl->queue, &priv->vpsl_list); priv->pbuf_vpsl = NULL; } + is_event_queue = false; } buf = priv->pbuf_vpsl; @@ -6142,7 +6144,8 @@ rkisp_params_aiisp_event_v35(struct rkisp_isp_params_vdev *params_vdev, u32 irq) ev_info->gain_index = buf->index; spin_unlock_irqrestore(&priv->buf_lock, lock_flags); } - v4l2_event_queue(dev->isp_sdev.sd.devnode, &ev); + if (is_event_queue) + v4l2_event_queue(dev->isp_sdev.sd.devnode, &ev); v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev, "%s seq:%d height:%d idx(iir:%d gain:%d vpsl:%d aipre:%d aiisp:%d ysrc:%d ydst:%d)\n", ev.id ? "isp_be" : "isp_fe", ev_info->sequence, ev_info->height, @@ -6161,7 +6164,7 @@ rkisp_params_aiisp_start_v35(struct rkisp_isp_params_vdev *params_vdev, unsigned long lock_flags = 0; u32 val, aiisp_rd, seq = st->sequence; - if (!dev->is_aiisp_en) + if (!dev->is_aiisp_en && !dev->is_aiisp_stop) return -EINVAL; v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev, "isp_be input seq:%d idx(iir:%d gain:%d vpsl:%d aipre:%d aiisp:%d)\n", @@ -6180,7 +6183,8 @@ rkisp_params_aiisp_start_v35(struct rkisp_isp_params_vdev *params_vdev, return -EINVAL; } - rkisp_params_cfg(params_vdev, seq, RKISP_PARAMS_LAT); + if (!dev->is_aiisp_stop) + rkisp_params_cfg(params_vdev, seq, RKISP_PARAMS_LAT); spin_lock_irqsave(&priv->buf_lock, lock_flags); buf = &priv->buf_bay3d_iir[st->iir_index]; @@ -6244,6 +6248,11 @@ rkisp_params_aiisp_start_v35(struct rkisp_isp_params_vdev *params_vdev, } spin_unlock_irqrestore(&priv->buf_lock, lock_flags); + if (dev->is_aiisp_stop) { + dev->hw_dev->is_be_idle = true; + rkisp_params_aiisp_event_v35(params_vdev, ISP3X_OUT_FRM_QUARTER); + return -EINVAL; + } val = params_vdev->is_hdr ? ISP35_B3DLDCH_RD_BASE_SHD : ISP3X_MI_RAW0_RD_BASE_SHD; v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev, "isp_be start seq:%d (%x %x | %x:%x %x:%x)\n", @@ -6336,6 +6345,9 @@ rkisp_params_aiisp_switch_v35(struct rkisp_isp_params_vdev *params_vdev, bool on val = ISP39_AIISP_LINECNT_DONE | ISP3X_OUT_FRM_QUARTER | ISP3X_BAY3D_FRM_END; rkisp_clear_bits(dev, CIF_ISP_IMSC, val, false); + + if (IS_HDR_RDBK(dev->rd_mode)) + dev->irq_ends_mask &= ~(ISP_FRAME_BNR | ISP_FRAME_VPSL); } else { val = rkisp_read(dev, ISP3X_ISP_CTRL1, false); val |= ISP35_BAYER_PAT_FE(params_vdev->raw_type) | ISP35_BAYER_UPD_FE_EN; @@ -6373,6 +6385,10 @@ rkisp_params_aiisp_switch_v35(struct rkisp_isp_params_vdev *params_vdev, bool on rkisp_write(dev, ISP35_AI_CTRL, val, false); params_vdev->cur_fe_frame_id = params_vdev->cur_frame_id; + if (IS_HDR_RDBK(dev->rd_mode)) { + dev->is_first_frame = true; + dev->irq_ends_mask = ISP_FRAME_BNR | ISP_FRAME_VPSL; + } } } diff --git a/drivers/media/platform/rockchip/isp/rkisp.c b/drivers/media/platform/rockchip/isp/rkisp.c index 0217f8ebd5c6..27ca6de91a6b 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.c +++ b/drivers/media/platform/rockchip/isp/rkisp.c @@ -1018,7 +1018,7 @@ run_next: cur_frame_id, dma2frm + 1, val, is_try); if (!hw->is_shutdown) { rkisp_unite_write(dev, CSI2RX_CTRL0, val, true); - if (dev->is_aiisp_sync && !dev->is_first_frame) { + if (dev->is_aiisp_en && dev->is_aiisp_sync && !dev->is_first_frame) { dev->irq_ends_mask |= ISP_FRAME_END; if (dev->isp_ver == ISP_V39) { val = rkisp_read(dev, ISP3X_MI_RD_CTRL2, false); @@ -1159,10 +1159,11 @@ static void rkisp_rdbk_trigger_handle(struct rkisp_device *dev, u32 cmd) goto end; if (isp->is_aiisp_sync && !isp->is_first_frame) { rkisp_rdbk_aiisp_event(isp, T_CMD_LEN, &len[id]); + if (len[id]) + is_aiisp_ready = true; /* wait isp_be frame input */ - if (len[id] == 0) + if (len[id] == 0 && isp->is_aiisp_en) goto end; - is_aiisp_ready = true; } v4l2_dbg(2, rkisp_debug, &isp->v4l2_dev, "trigger fifo len:%d\n", max); @@ -1396,6 +1397,7 @@ end: if (dev->is_wait_aiq && (dev->unite_div < ISP_UNITE_DIV2 || dev->unite_index == ISP_UNITE_RIGHT)) return; + rkisp_config_aiisp(dev); if (dev->hw_dev->is_dvfs) schedule_work(&dev->rdbk_work); else @@ -3967,7 +3969,7 @@ static void rkisp_config_aiisp(struct rkisp_device *dev) irq = ISP39_AIISP_LINECNT_DONE; if (dev->aiisp_cfg.rd_linecnt) irq |= ISP3X_OUT_FRM_QUARTER; - + /* init aiisp stop */ if (!(dev->isp_state & ISP_START) && dev->is_aiisp_stop) goto unlock; @@ -3977,14 +3979,19 @@ static void rkisp_config_aiisp(struct rkisp_device *dev) dev->aiisp_stop_seq = dev->dmarx_dev.cur_frame.id; goto unlock; } else { - dev->is_aiisp_en = false; irq = 0; + dev->is_aiisp_en = false; + dev->is_aiisp_stop = true; + if (dev->params_vdev.ops->aiisp_switch) + dev->params_vdev.ops->aiisp_switch(&dev->params_vdev, false); } } else if (!dev->is_aiisp_en && dev->aiisp_cfg.mode) { dev->is_aiisp_en = true; dev->is_aiisp_stop = false; if (dev->params_vdev.ops->aiisp_switch) dev->params_vdev.ops->aiisp_switch(&dev->params_vdev, true); + if (!dev->hw_dev->is_single || IS_HDR_RDBK(dev->rd_mode)) + dev->is_aiisp_sync = true; } if (dev->is_aiisp_en) { @@ -4027,19 +4034,32 @@ static int rkisp_set_aiisp_linecnt(struct rkisp_device *dev, struct rkisp_aiisp_cfg *cfg) { unsigned long lock_flags = 0; + int ret = -EINVAL; if (dev->isp_ver != ISP_V39 && dev->isp_ver != ISP_V35) - return -EINVAL; + return ret; + v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, + "%s mode:%d wr:%d rd:%d wr_mode:%d\n", __func__, + cfg->mode, cfg->wr_linecnt, cfg->rd_linecnt, cfg->wr_mode); spin_lock_irqsave(&dev->aiisp_lock, lock_flags); if (!(dev->isp_state & ISP_START)) { - if (!cfg->mode && cfg->wr_linecnt && cfg->rd_linecnt) + if (!cfg->mode && cfg->wr_linecnt && cfg->rd_linecnt) { + /* TODO support multi-sensor */ + if (!dev->hw_dev->is_single) { + dev_err(dev->dev, + "aibnr no support dynamic switch for multi-sensor now\n"); + goto unlock; + } dev->is_aiisp_stop = true; + } dev->is_aiisp_en = !!cfg->mode; } dev->is_aiisp_upd = true; dev->aiisp_cfg = *cfg; + ret = 0; +unlock: spin_unlock_irqrestore(&dev->aiisp_lock, lock_flags); - return 0; + return ret; } static int rkisp_get_aiisp_linecnt(struct rkisp_device *dev, @@ -4135,7 +4155,7 @@ static int rkisp_rdbk_aiisp_event(struct rkisp_device *dev, u32 cmd, void *arg) stream->ops->push_buf(stream); } - if (!dev->is_aiisp_en) + if (!dev->is_aiisp_en && !dev->is_aiisp_stop) return -EINVAL; spin_lock_irqsave(&dev->rdbk_lock, lock_flags); @@ -4163,7 +4183,8 @@ static int rkisp_rdbk_aiisp_event(struct rkisp_device *dev, u32 cmd, void *arg) } spin_unlock_irqrestore(&dev->rdbk_lock, lock_flags); - if (dev->is_aiisp_sync && arg && cmd == T_CMD_QUEUE) { + if (dev->is_aiisp_en && dev->is_aiisp_sync && + arg && cmd == T_CMD_QUEUE) { if (dev->hw_dev->is_idle) rkisp_rdbk_trigger_event(dev, T_CMD_QUEUE, NULL); goto end; From e8cba62d567149fd39c5ff1029b315081eac90b7 Mon Sep 17 00:00:00 2001 From: Damon Ding Date: Tue, 8 Oct 2024 20:14:01 +0800 Subject: [PATCH 08/15] drm/rockchip: vop2: Add "DIMMING_DATA" property for local dimming The user can update the dimming data via "DIMMING_DATA" property, and it will be sent to the panel supported local dimming function in the rockchip dimming panel driver. Change-Id: I7dba541450fce86be064d0205af0f595b1712aea Signed-off-by: Damon Ding --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 3 +++ drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 6 ++++++ drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 19 +++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 4288476f8ab6..99819921eeea 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -1516,6 +1516,9 @@ static int rockchip_drm_create_properties(struct drm_device *dev) private->cubic_lut_size_prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "CUBIC_LUT_SIZE", 0, UINT_MAX); + private->dimming_data_prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, + "DIMMING_DATA", 0); + return drm_mode_create_tv_properties(dev, 0, NULL); } diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index b166d1f56c50..8bd377c3fdcd 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -298,6 +298,8 @@ struct rockchip_crtc_state { */ bool sharp_en; + bool dimming_changed; + struct drm_tv_connector_state *tv_state; int left_margin; int right_margin; @@ -347,6 +349,7 @@ struct rockchip_crtc_state { struct drm_property_blob *post_csc_data; struct drm_property_blob *post_sharp_data; struct drm_property_blob *cubic_lut_data; + struct drm_property_blob *dimming_data; int request_refresh_rate; int max_refresh_rate; @@ -579,6 +582,9 @@ struct rockchip_drm_private { struct drm_property *connector_id_prop; struct drm_property *split_area_prop; + /* private local dimming prop */ + struct drm_property *dimming_data_prop; + const struct rockchip_crtc_funcs *crtc_funcs[ROCKCHIP_MAX_CRTC]; uint64_t iommu_fault_count; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index d57bf7c676a1..4222fc27bc75 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -13635,6 +13635,8 @@ static struct drm_crtc_state *vop2_crtc_duplicate_state(struct drm_crtc *crtc) drm_property_blob_get(vcstate->cubic_lut_data); if (vcstate->post_sharp_data) drm_property_blob_get(vcstate->post_sharp_data); + if (vcstate->dimming_data) + drm_property_blob_get(vcstate->dimming_data); __drm_atomic_helper_crtc_duplicate_state(crtc, &vcstate->base); return &vcstate->base; @@ -13651,6 +13653,7 @@ static void vop2_crtc_destroy_state(struct drm_crtc *crtc, drm_property_blob_put(vcstate->post_csc_data); drm_property_blob_put(vcstate->cubic_lut_data); drm_property_blob_put(vcstate->post_sharp_data); + drm_property_blob_put(vcstate->dimming_data); kfree(vcstate); } @@ -13846,6 +13849,11 @@ static int vop2_crtc_atomic_get_property(struct drm_crtc *crtc, return 0; } + if (property == private->dimming_data_prop) { + *val = (vcstate->dimming_data) ? vcstate->dimming_data->base.id : 0; + return 0; + } + DRM_ERROR("failed to get vop2 crtc property: %s\n", property->name); return -EINVAL; @@ -14006,6 +14014,16 @@ static int vop2_crtc_atomic_set_property(struct drm_crtc *crtc, return ret; } + if (property == private->dimming_data_prop) { + ret = vop2_atomic_replace_property_blob_from_id(drm_dev, + &vcstate->dimming_data, + val, + -1, -1, + &replaced); + vcstate->dimming_changed |= replaced; + return ret; + } + DRM_ERROR("failed to set vop2 crtc property %s\n", property->name); return -EINVAL; @@ -15327,6 +15345,7 @@ static int vop2_create_crtc(struct vop2 *vop2, uint8_t enabled_vp_mask) drm_object_attach_property(&crtc->base, private->aclk_prop, 0); drm_object_attach_property(&crtc->base, private->bg_prop, 0); drm_object_attach_property(&crtc->base, private->line_flag_prop, 0); + drm_object_attach_property(&crtc->base, private->dimming_data_prop, 0); if (vp_data->feature & VOP_FEATURE_OVERSCAN) { drm_object_attach_property(&crtc->base, drm_dev->mode_config.tv_left_margin_property, 100); From 2cd7ed573f6ae491d1cc7fe9041c0a9107e6fdfa Mon Sep 17 00:00:00 2001 From: Wei Dun Date: Tue, 24 Jun 2025 11:12:25 +0800 Subject: [PATCH 09/15] media: rockchip: vpss: offline mode support auto unite output Change-Id: I234f7c5af53e855e0faebf791d3db74d94e33022 Signed-off-by: Wei Dun --- .../media/platform/rockchip/vpss/regs_v20.h | 9 + .../platform/rockchip/vpss/vpss_offline_v20.c | 175 +++++++++++++++--- 2 files changed, 154 insertions(+), 30 deletions(-) diff --git a/drivers/media/platform/rockchip/vpss/regs_v20.h b/drivers/media/platform/rockchip/vpss/regs_v20.h index f6b01e3db9cf..6eb86c8083ad 100644 --- a/drivers/media/platform/rockchip/vpss/regs_v20.h +++ b/drivers/media/platform/rockchip/vpss/regs_v20.h @@ -296,8 +296,17 @@ /* SCALE_CTRL */ +#define RKVPSS2X_SW_SCL_HY_EN BIT(0) +#define RKVPSS2X_SW_SCL_HC_EN BIT(1) +#define RKVPSS2X_SW_SCL_VY_EN BIT(2) +#define RKVPSS2X_SW_SCL_VC_EN BIT(3) #define RKVPSS2X_SW_AVG_SCALE_H_EN BIT(8) #define RKVPSS2X_SW_AVG_SCALE_V_EN BIT(9) +#define RKVPSS2X_SW_SCL_HPHASE_EN BIT(12) +#define RKVPSS2X_SW_SCL_CLIP_EN BIT(13) +#define RKVPSS2X_SW_SCL_IN_CLIP_EN BIT(14) +#define RKVPSS2X_SW_SCL_422TO420_EN BIT(30) +#define RKVPSS2X_SW_SCL_YUV420_REAL_EN BIT(31) /* MI_FORCE_UPDATE */ #define RKVPSS2X_MI_CHN4_FORCE_UPD BIT(8) diff --git a/drivers/media/platform/rockchip/vpss/vpss_offline_v20.c b/drivers/media/platform/rockchip/vpss/vpss_offline_v20.c index a1f927c017f1..2802a156befb 100644 --- a/drivers/media/platform/rockchip/vpss/vpss_offline_v20.c +++ b/drivers/media/platform/rockchip/vpss/vpss_offline_v20.c @@ -324,32 +324,124 @@ static void average_scale_down(struct rkvpss_frame_cfg *frame_cfg, rkvpss_hw_set_bits(hw, RKVPSS_VPSS_CLK_GATE, clk_mask, clk_mask); if (!unite) { - if (in_w == out_w && in_h == out_w) + if (in_w == out_w && in_h == out_h) goto end; val = in_w | (in_h << 16); - rkvpss_hw_write(hw, reg_base + 0x8, val); + rkvpss_hw_write(hw, reg_base + 0x8, val); /* input size */ val = out_w | (out_h << 16); - rkvpss_hw_write(hw, reg_base + 0xc, val); + rkvpss_hw_write(hw, reg_base + 0xc, val); /* output size */ if (in_w != out_w) { val = (out_w - 1) * 65536 / (in_w - 1) + 1; - rkvpss_hw_write(hw, reg_base + 0x10, val); - val = (out_w / 2 - 1) * 65536 / (in_w / 2 - 1) + 1; - rkvpss_hw_write(hw, reg_base + 0x14, val); - - ctrl |= RKVPSS_SCL_HY_EN | RKVPSS_SCL_HC_EN | RKVPSS2X_SW_AVG_SCALE_H_EN; + rkvpss_hw_write(hw, reg_base + 0x10, val); /* y_w_fac */ + rkvpss_hw_write(hw, reg_base + 0x14, val); /* c_w_fac */ + ctrl |= RKVPSS2X_SW_SCL_HY_EN | RKVPSS2X_SW_SCL_HC_EN | + RKVPSS2X_SW_AVG_SCALE_H_EN; } + if (in_h != out_h) { val = (out_h - 1) * 65536 / (in_h - 1) + 1; - rkvpss_hw_write(hw, reg_base + 0x18, val); - val = (out_h - 1) * 65536 / (in_h - 1) + 1; - rkvpss_hw_write(hw, reg_base + 0x1c, val); + rkvpss_hw_write(hw, reg_base + 0x18, val); /* y_h_fac */ + rkvpss_hw_write(hw, reg_base + 0x1c, val); /* c_h_fac */ + ctrl |= RKVPSS2X_SW_SCL_VY_EN | RKVPSS2X_SW_SCL_VC_EN | + RKVPSS2X_SW_AVG_SCALE_V_EN; + } + } else { + u32 in_width = cfg->crop_width / 2; + u32 out_width = cfg->scl_width / 2; + u32 overlap = UNITE_ENLARGE; - ctrl |= RKVPSS_SCL_VY_EN | RKVPSS_SCL_VC_EN | RKVPSS2X_SW_AVG_SCALE_V_EN; + if (left) { + /* Left side processing */ + rkvpss_hw_write(hw, reg_base + 0x50, 0); /* in_crop_offs */ + rkvpss_hw_write(hw, reg_base + 0x20, 0); /* hy_offs */ + rkvpss_hw_write(hw, reg_base + 0x24, 0); /* hc_offs */ + rkvpss_hw_write(hw, reg_base + 0x28, 0); /* vy_offs */ + rkvpss_hw_write(hw, reg_base + 0x2c, 0); /* vc_offs */ + rkvpss_hw_write(hw, reg_base + 0x48, 0); /* hy_offs_mi */ + rkvpss_hw_write(hw, reg_base + 0x4c, 0); /* hc_offs_mi */ + + u32 in_w_for_hw = (in_width == out_width) ? in_width : (in_width + overlap); + u32 aligned_width = ALIGN(in_w_for_hw, 16); + + val = aligned_width | (cfg->crop_height << 16); + rkvpss_hw_write(hw, reg_base + 0x8, val); /* input size */ + + aligned_width = ALIGN(out_width, 16); + val = aligned_width | (cfg->scl_height << 16); + rkvpss_hw_write(hw, reg_base + 0xc, val); /* output size */ + + ctrl |= RKVPSS2X_SW_SCL_CLIP_EN; + } else { + /* Right side processing */ + val = ofl->unite_params[idx].scl_in_crop_w_y | + (ofl->unite_params[idx].scl_in_crop_w_c << 4); + rkvpss_hw_write(hw, reg_base + 0x50, val); /* in_crop_offs */ + + ctrl |= RKVPSS2X_SW_SCL_HPHASE_EN; + + u32 y_phase = ofl->unite_params[idx].y_w_phase; + u32 c_phase = ofl->unite_params[idx].c_w_phase; + + rkvpss_hw_write(hw, reg_base + 0x20, y_phase); /* hy_offs */ + rkvpss_hw_write(hw, reg_base + 0x24, c_phase); /* hc_offs */ + rkvpss_hw_write(hw, reg_base + 0x28, 0); /* vy_offs */ + rkvpss_hw_write(hw, reg_base + 0x2c, 0); /* vc_offs */ + + val = 16 - (cfg->scl_width / 2 & 0xf); + if (val == 16) + val = 0; + rkvpss_hw_write(hw, reg_base + 0x48, val); /* hy_offs_mi */ + rkvpss_hw_write(hw, reg_base + 0x4c, val); /* hc_offs_mi */ + + u32 in_w_for_hw = (in_width == out_width) ? in_width : (in_width + overlap); + u32 aligned_width = ALIGN(in_w_for_hw, 16); + + val = aligned_width | (cfg->crop_height << 16); + rkvpss_hw_write(hw, reg_base + 0x8, val); /* input size */ + + aligned_width = ALIGN(out_width, 16); + val = aligned_width | (cfg->scl_height << 16); + rkvpss_hw_write(hw, reg_base + 0xc, val); /* output size */ + + v4l2_dbg(1, rkvpss_debug, &ofl->v4l2_dev, + "Right side: in_w=%d out_w=%d y_phase=0x%x c_phase=0x%x mi_offset=0x%x\n", + aligned_width, out_width, y_phase, c_phase, val); + + if (in_width != out_width) { + ctrl |= RKVPSS2X_SW_SCL_HY_EN | RKVPSS2X_SW_SCL_HC_EN | + RKVPSS2X_SW_AVG_SCALE_H_EN; + } + if (cfg->crop_height != cfg->scl_height) { + ctrl |= RKVPSS2X_SW_SCL_VY_EN | RKVPSS2X_SW_SCL_VC_EN | + RKVPSS2X_SW_AVG_SCALE_V_EN; + } + + if (overlap > 0) { + ctrl |= RKVPSS2X_SW_SCL_CLIP_EN; + if (aligned_width > out_width) + ctrl |= RKVPSS2X_SW_SCL_IN_CLIP_EN; + } + } + + if (cfg->scl_width != frame_cfg->input.width) { + val = ofl->unite_params[idx].y_w_fac; + rkvpss_hw_write(hw, reg_base + 0x10, val); /* y_w_fac */ + val = ofl->unite_params[idx].c_w_fac; + rkvpss_hw_write(hw, reg_base + 0x14, val); /* c_w_fac */ + ctrl |= RKVPSS2X_SW_SCL_HY_EN | RKVPSS2X_SW_SCL_HC_EN | + RKVPSS2X_SW_AVG_SCALE_H_EN; + } + if (cfg->scl_height != frame_cfg->input.height) { + val = ofl->unite_params[idx].y_h_fac; + rkvpss_hw_write(hw, reg_base + 0x18, val); /* y_h_fac */ + val = ofl->unite_params[idx].c_h_fac; + rkvpss_hw_write(hw, reg_base + 0x1c, val); /* c_h_fac */ + ctrl |= RKVPSS2X_SW_SCL_VY_EN | RKVPSS2X_SW_SCL_VC_EN | + RKVPSS2X_SW_AVG_SCALE_V_EN; } } - //unite todo end: rkvpss_hw_write(hw, reg_base, ctrl); @@ -410,7 +502,7 @@ static void bilinear_scale(struct rkvpss_frame_cfg *frame_cfg, rkvpss_hw_set_bits(hw, RKVPSS_VPSS_CLK_GATE, clk_mask, clk_mask); if (!unite) { - if (in_w == out_w && in_h == out_w) + if (in_w == out_w && in_h == out_h) goto end; /* TODO diff for input and output format */ @@ -507,14 +599,42 @@ static void scale_config(struct rkvpss_offline_dev *ofl, struct rkvpss_frame_cfg *cfg, bool unite, bool left) { int i; + bool is_downscale_w; + bool is_downscale_h; + bool use_average; for (i = 0; i < RKVPSS_OUT_V20_MAX; i++) { if (!cfg->output[i].enable) continue; - if ((i == 0 || i == 2) && cfg->output[i].avg_scl_down) - average_scale_down(cfg, ofl, &cfg->output[i], i, unite, left); - else - bilinear_scale(cfg, ofl, &cfg->output[i], i, unite, left); + is_downscale_w = cfg->output[i].scl_width <= cfg->output[i].crop_width; + is_downscale_h = cfg->output[i].scl_height <= cfg->output[i].crop_height; + use_average = is_downscale_w && is_downscale_h; + + /* channel 0 and 2 use average_scale_down when downscale */ + if (use_average && (i == RKVPSS_OUTPUT_CH0 || i == RKVPSS_OUTPUT_CH2)) { + if (unite) { + v4l2_dbg(2, rkvpss_debug, &ofl->v4l2_dev, + "Unite mode: average_scale_down for channel %d\n", i); + average_scale_down(cfg, ofl, &cfg->output[i], i, true, true); + average_scale_down(cfg, ofl, &cfg->output[i], i, true, false); + } else { + v4l2_dbg(2, rkvpss_debug, &ofl->v4l2_dev, + "Normal mode: average_scale_down for channel %d\n", i); + average_scale_down(cfg, ofl, &cfg->output[i], i, false, false); + } + } else { + /* use bilinear_scale for other channels */ + if (unite) { + v4l2_dbg(2, rkvpss_debug, &ofl->v4l2_dev, + "Unite mode: bilinear_scale for channel %d\n", i); + bilinear_scale(cfg, ofl, &cfg->output[i], i, true, true); + bilinear_scale(cfg, ofl, &cfg->output[i], i, true, false); + } else { + v4l2_dbg(2, rkvpss_debug, &ofl->v4l2_dev, + "Normal mode: bilinear_scale for channel %d\n", i); + bilinear_scale(cfg, ofl, &cfg->output[i], i, false, false); + } + } } } @@ -1912,12 +2032,6 @@ int rkvpss_check_params(struct rkvpss_offline_dev *ofl, goto end; } - /* set unite mode */ - if (cfg->input.width > RKVPSS_MAX_WIDTH_V20) - *unite = true; - else - *unite = false; - /* check input format */ switch (cfg->input.format) { case V4L2_PIX_FMT_NV16: @@ -2044,6 +2158,12 @@ int rkvpss_check_params(struct rkvpss_offline_dev *ofl, goto end; } + /* set unite mode */ + if (out_width > RKVPSS_MAX_WIDTH_V20) + *unite = true; + else + *unite = false; + /* check crop */ cfg->output[i].crop_h_offs = ALIGN(cfg->output[i].crop_h_offs, 2); cfg->output[i].crop_v_offs = ALIGN(cfg->output[i].crop_v_offs, 2); @@ -2233,12 +2353,7 @@ int rkvpss_check_params(struct rkvpss_offline_dev *ofl, ret = -EINVAL; goto end; } - if (cfg->output[i].scl_width > cfg->input.width) { - v4l2_err(&ofl->v4l2_dev, "dev_id:%d unite horizontal no support scale up\n", - cfg->dev_id); - ret = -EINVAL; - goto end; - } + if (cfg->output[i].aspt.enable) { v4l2_err(&ofl->v4l2_dev, "dev_id:%d unite no support aspt\n", cfg->dev_id); From 1f43a694eabf5309061333ba6290404298f906ca Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Wed, 2 Jul 2025 15:26:05 +0800 Subject: [PATCH 10/15] soc: rockchip: cpuinfo: export chip unique id to userspace root@linaro-alip:/# cat /sys/module/rockchip_cpuinfo/parameters/id 4132475458000000000000000006150b Change-Id: Idfb80ed48e4b507d81731c63004686f37b745b45 Signed-off-by: Liang Chen --- drivers/soc/rockchip/rockchip-cpuinfo.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/soc/rockchip/rockchip-cpuinfo.c b/drivers/soc/rockchip/rockchip-cpuinfo.c index 9c954e5fc6d0..6e25271669a1 100644 --- a/drivers/soc/rockchip/rockchip-cpuinfo.c +++ b/drivers/soc/rockchip/rockchip-cpuinfo.c @@ -24,6 +24,9 @@ unsigned long rockchip_soc_id; EXPORT_SYMBOL(rockchip_soc_id); +static char id[33] = "0"; +module_param_string(id, id, sizeof(id), 0444); + static int rk3566_soc_init(struct device *dev) { struct nvmem_cell *cell; @@ -133,6 +136,7 @@ skip_cpu_code: for (i = 0; i < 8; i++) { buf[i] = efuse_buf[1 + (i << 1)]; buf[i + 8] = efuse_buf[i << 1]; + sprintf(id + i * 4, "%02x%02x", efuse_buf[i << 1], efuse_buf[1 + (i << 1)]); } kfree(efuse_buf); From 77c92aee865b28f721c7cab5808d2c8d74027c42 Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Wed, 2 Jul 2025 17:17:19 +0800 Subject: [PATCH 11/15] rtc: rockchip: add ready flag for rtc setting time Change-Id: I0f1ddcf41ae4891c40ed2d4ec05e1a9b38f786b6 Signed-off-by: Elaine Zhang --- drivers/rtc/rtc-rockchip.c | 44 +++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/drivers/rtc/rtc-rockchip.c b/drivers/rtc/rtc-rockchip.c index d26a07f5a904..710346ceee3a 100644 --- a/drivers/rtc/rtc-rockchip.c +++ b/drivers/rtc/rtc-rockchip.c @@ -87,6 +87,7 @@ /* RTC_CTRL_REG bitfields */ #define RTC_CTRL_REG_START_RTC BIT(0) #define RTC_TIMEOUT (3000 * 1000) +#define RTC_STATUS_TIMEOUT (500) /* RK630 has a shadowed register for saving a "frozen" RTC time. * When user setting "GET_TIME" to 1, the time will save in this shadowed @@ -256,8 +257,7 @@ static int rockchip_rtc_read_time(struct device *dev, struct rtc_time *tm) return ret; } -/* Set current time and date in RTC */ -static int rockchip_rtc_set_time(struct device *dev, struct rtc_time *tm) +static int rockchip_rtc_do_set_time(struct device *dev, struct rtc_time *tm, bool ready) { struct rockchip_rtc *rtc = dev_get_drvdata(dev); u32 rtc_data[NUM_TIME_REGS]; @@ -292,13 +292,15 @@ static int rockchip_rtc_set_time(struct device *dev, struct rtc_time *tm) return ret; } - ret = regmap_read_poll_timeout(rtc->regmap, RTC_STATUS1, status, - !(status & RTC_CTRL_REG_START_RTC), - 0, RTC_TIMEOUT); - if (ret) - dev_err(dev, - "%s:timeout Update RTC_STATUS1 : %d\n", - __func__, ret); + if (ready) { + ret = regmap_read_poll_timeout(rtc->regmap, RTC_STATUS1, status, + !(status & RTC_CTRL_REG_START_RTC), + 100, RTC_STATUS_TIMEOUT); + if (ret) + dev_err(dev, + "%s:timeout Update RTC_STATUS1 : %d\n", + __func__, ret); + } ret = regmap_bulk_write(rtc->regmap, RTC_SET_SECONDS, rtc_data, NUM_TIME_REGS); @@ -318,17 +320,25 @@ static int rockchip_rtc_set_time(struct device *dev, struct rtc_time *tm) return ret; } - ret = regmap_read_poll_timeout(rtc->regmap, RTC_STATUS1, status, - (status & RTC_CTRL_REG_START_RTC), - 0, RTC_TIMEOUT); - if (ret) - dev_err(dev, - "%s:timeout Update RTC_STATUS1 : %d\n", - __func__, ret); + if (ready) { + ret = regmap_read_poll_timeout(rtc->regmap, RTC_STATUS1, status, + (status & RTC_CTRL_REG_START_RTC), + 100, RTC_STATUS_TIMEOUT); + if (ret) + dev_err(dev, + "%s:timeout Update RTC_STATUS1 : %d\n", + __func__, ret); + } return 0; } +/* Set current time and date in RTC */ +static int rockchip_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + return rockchip_rtc_do_set_time(dev, tm, true); +} + /* Read alarm time and date in RTC */ static int rockchip_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) { @@ -948,7 +958,7 @@ static int rockchip_rtc_probe(struct platform_device *pdev) rockchip_rtc_read_time(&pdev->dev, &tm_read); if (rtc_valid_tm(&tm_read) != 0) - rockchip_rtc_set_time(&pdev->dev, &tm); + rockchip_rtc_do_set_time(&pdev->dev, &tm, false); rtc->irq = platform_get_irq(pdev, 0); if (rtc->irq < 0) From 8faaf5ea8a5331f11b8b313df819d1f1331e21af Mon Sep 17 00:00:00 2001 From: hkj Date: Thu, 15 May 2025 17:33:54 +0800 Subject: [PATCH 12/15] media: rockchip: aiisp: modify for aiynr algo Change-Id: If8189c7ea66ac572ad4f8ac335d7f365c24d29f7 Signed-off-by: hkj --- drivers/media/platform/rockchip/aiisp/aiisp.c | 278 ++++++++++++++++-- drivers/media/platform/rockchip/aiisp/aiisp.h | 8 +- drivers/media/platform/rockchip/aiisp/hw.c | 24 +- include/soc/rockchip/rockchip_aiisp.h | 30 ++ include/uapi/linux/rk-aiisp-config.h | 18 +- 5 files changed, 311 insertions(+), 47 deletions(-) create mode 100644 include/soc/rockchip/rockchip_aiisp.h diff --git a/drivers/media/platform/rockchip/aiisp/aiisp.c b/drivers/media/platform/rockchip/aiisp/aiisp.c index 8ae4ffbe429a..d354c8ea0167 100644 --- a/drivers/media/platform/rockchip/aiisp/aiisp.c +++ b/drivers/media/platform/rockchip/aiisp/aiisp.c @@ -123,7 +123,7 @@ static void rkaiisp_update_regs(struct rkaiisp_device *aidev, u32 start, u32 end } } -void rkaiisp_update_list_reg(struct rkaiisp_device *aidev) +static void rkaiisp_update_list_reg(struct rkaiisp_device *aidev) { rkaiisp_update_regs(aidev, AIISP_MI_CTRL, AIISP_MI_CTRL); rkaiisp_update_regs(aidev, AIISP_MI_SLICE_CTRL, AIISP_MI_MANUAL_CTRL); @@ -355,8 +355,8 @@ static void rkaiisp_detach_dmabuf(struct rkaiisp_device *aidev, { if (buffer->dma_fd >= 0) { v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, - "%s buf:%pad size:%d\n", __func__, - &buffer->dma_addr, buffer->size); + "%s dma_fd:%d, buf:%pad size:%d\n", __func__, + buffer->dma_fd, &buffer->dma_addr, buffer->size); dma_buf_unmap_attachment(buffer->dba, buffer->sgt, DMA_BIDIRECTIONAL); dma_buf_detach(buffer->dmabuf, buffer->dba); dma_buf_put(buffer->dmabuf); @@ -365,6 +365,36 @@ static void rkaiisp_detach_dmabuf(struct rkaiisp_device *aidev, } } +static void rkaiisp_free_aiynr_ybuf(struct rkaiisp_device *aidev) +{ + struct aiisp_aiynr_ybuf_cfg *buf_cfg = &aidev->ynr_ybuf_cfg; + struct rkaiisp_dummy_buffer *ynroutbuf = &aidev->ynroutbuf[0]; + int i; + + for (i = 0; i < buf_cfg->buf_cnt; i++) { + if (buf_cfg->buf[i]) { + v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, + "%s buf:%pad size:%zu dmabuf:%p\n", __func__, + &ynroutbuf[i].dma_addr, ynroutbuf[i].dmabuf->size, + buf_cfg->buf[i]); + if (ynroutbuf[i].dba) { + if (ynroutbuf[i].sgt) { + dma_buf_unmap_attachment(ynroutbuf[i].dba, + ynroutbuf[i].sgt, + DMA_BIDIRECTIONAL); + ynroutbuf[i].sgt = NULL; + } + dma_buf_detach(ynroutbuf[i].dmabuf, ynroutbuf[i].dba); + dma_buf_put(ynroutbuf[i].dmabuf); + ynroutbuf[i].dba = NULL; + } + buf_cfg->buf[i] = NULL; + } + } + + buf_cfg->buf_cnt = 0; +} + static void rkaiisp_free_tempbuf(struct rkaiisp_device *aidev) { rkaiisp_free_buffer(aidev, &aidev->temp_buf[0]); @@ -394,7 +424,13 @@ static int rkaiisp_free_pool(struct rkaiisp_device *aidev) for (i = 0; i < ispbuf->bnr_buf.u.v35.aiisp.buf_cnt; i++) rkaiisp_detach_dmabuf(aidev, &aidev->aiispbuf[i]); + for (i = 0; i < ispbuf->bnr_buf.u.v35.y_src.buf_cnt; i++) + rkaiisp_detach_dmabuf(aidev, &aidev->ynrinbuf[i]); + rkaiisp_free_tempbuf(aidev); + if (aidev->exealgo == AIYNR) + rkaiisp_free_aiynr_ybuf(aidev); + aidev->init_buf = false; v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, "free buf poll\n"); @@ -432,9 +468,10 @@ static int rkaiisp_attach_dmabuf(struct rkaiisp_device *aidev, buffer->sgt = sgt; buffer->dma_addr = sg_dma_address(sgt->sgl); buffer->size = sg_dma_len(sgt->sgl); + buffer->vaddr = NULL; v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, - "%s buf:%pad size:%d\n", __func__, - &buffer->dma_addr, buffer->size); + "%s dma_fd:%d, buf:%pad size:%d\n", __func__, + buffer->dma_fd, &buffer->dma_addr, buffer->size); return ret; } @@ -446,6 +483,26 @@ static void rkaiisp_calc_outbuf_size(struct rkaiisp_device *aidev, u32 raw_hgt, if (aidev->model_mode == REMOSAIC_MODE) return; + if (aidev->model_mode == AIYNR_MODE) { + for (i = 0; i < RKAIISP_AIYNR_LAYER_NUM; i++) { + if (i == 0) { + aidev->outbuf_size[i].height = raw_hgt; + aidev->outbuf_size[i].width = raw_wid; + aidev->outbuf_size[i].channel = 1; + aidev->outbuf_size[i].stride = raw_wid; + } else { + aidev->outbuf_size[i].height = raw_hgt / 2; + aidev->outbuf_size[i].width = raw_wid / 2; + aidev->outbuf_size[i].channel = 8; + aidev->outbuf_size[i].stride = raw_wid * 8; + } + + raw_hgt = CEIL_BY(CEIL_DOWN(raw_hgt, 2), 2); + raw_wid = CEIL_BY(CEIL_DOWN(raw_wid, 2), 2); + } + return; + } + if (aidev->model_mode == SINGLEX2_MODE) { for (i = 0; i < RKAIISP_PYRAMID_LAYER_NUM; i++) { if (i == 0) { @@ -494,7 +551,7 @@ static void rkaiisp_calc_outbuf_size(struct rkaiisp_device *aidev, u32 raw_hgt, static int rkaiisp_init_pool(struct rkaiisp_device *aidev, struct rkaiisp_ispbuf_info *ispbuf) { int i, ret = 0; - u32 stride; + u32 stride, size; for (i = 0; i < ispbuf->bnr_buf.iir.buf_cnt; i++) { aidev->iirbuf[i].dma_fd = ispbuf->bnr_buf.iir.buf_fd[i]; @@ -536,9 +593,25 @@ static int rkaiisp_init_pool(struct rkaiisp_device *aidev, struct rkaiisp_ispbuf return -EINVAL; } } + for (i = 0; i < ispbuf->bnr_buf.u.v35.y_src.buf_cnt; i++) { + aidev->ynrinbuf[i].dma_fd = ispbuf->bnr_buf.u.v35.y_src.buf_fd[i]; + ret = rkaiisp_attach_dmabuf(aidev, &aidev->ynrinbuf[i]); - stride = ((ispbuf->iir_width + 1) / 2 * 15 * 11 + 7) >> 3; - aidev->temp_buf[0].size = stride * (ispbuf->iir_height + 1) / 2; + if (ret) { + rkaiisp_free_pool(aidev); + v4l2_err(&aidev->v4l2_dev, "attach dmabuf failed: %d\n", ret); + return -EINVAL; + } + } + + if (aidev->exealgo == AIYNR) { + stride = ((ispbuf->iir_width + 3) / 4 * 8 * 11 + 7) >> 3; + size = stride * (ispbuf->iir_height + 3) / 4; + } else { + stride = ((ispbuf->iir_width + 1) / 2 * 15 * 11 + 7) >> 3; + size = stride * (ispbuf->iir_height + 1) / 2; + } + aidev->temp_buf[0].size = size; aidev->temp_buf[1].size = aidev->temp_buf[0].size; aidev->temp_buf[0].is_need_vaddr = false; aidev->temp_buf[0].is_need_dbuf = false; @@ -635,7 +708,7 @@ static int rkaiisp_init_airms_pool(struct rkaiisp_device *aidev, struct rkaiisp_ return ret; } -int rkaiisp_queue_ispbuf(struct rkaiisp_device *aidev, union rkaiisp_queue_buf *idxbuf) +static int rkaiisp_queue_ispbuf(struct rkaiisp_device *aidev, union rkaiisp_queue_buf *idxbuf) { struct kfifo *fifo = &aidev->idxbuf_kfifo; struct rkaiisp_hw_dev *hw_dev = aidev->hw_dev; @@ -656,10 +729,10 @@ int rkaiisp_queue_ispbuf(struct rkaiisp_device *aidev, union rkaiisp_queue_buf * else v4l2_err(&aidev->v4l2_dev, "fifo is full\n"); - if (aidev->exealgo == AIBNR) - sequence = idxbuf->aibnr_st.sequence; - else if (aidev->exealgo == AIRMS) + if (aidev->exealgo == AIRMS) sequence = idxbuf->airms_st.sequence; + else + sequence = idxbuf->aibnr_st.sequence; v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, "idxbuf fifo in: %d\n", sequence); @@ -676,6 +749,40 @@ int rkaiisp_queue_ispbuf(struct rkaiisp_device *aidev, union rkaiisp_queue_buf * return ret; } +static int rkaiisp_get_ynrbuf_info(struct rkaiisp_device *aidev, + struct rkaiisp_ynrbuf_info *ynrbuf_info) +{ + + struct aiisp_aiynr_ybuf_cfg *buf_cfg = &aidev->ynr_ybuf_cfg; + struct rkaiisp_dummy_buffer *ynroutbuf = &aidev->ynroutbuf[0]; + u32 buf_cnt; + int i; + + buf_cnt = buf_cfg->buf_cnt; + if (buf_cnt > RKAIISP_AIYNR_YBUF_NUM_MAX) { + v4l2_err(&aidev->v4l2_dev, + "%s ynroutbuf cnt(%d) is too big\n", __func__, + buf_cnt); + buf_cnt = RKAIISP_AIYNR_YBUF_NUM_MAX; + } + ynrbuf_info->width = buf_cfg->width; + ynrbuf_info->height = buf_cfg->height; + ynrbuf_info->buf_cnt = 0; + for (i = 0; i < buf_cnt; i++) { + if (buf_cfg->buf[i]) { + ynroutbuf[i].dma_fd = dma_buf_fd(ynroutbuf[i].dmabuf, O_CLOEXEC); + if (ynroutbuf[i].dma_fd < 0) + return -EINVAL; + + get_dma_buf(ynroutbuf[i].dmabuf); + ynrbuf_info->dma_fd[i] = ynroutbuf[i].dma_fd; + ynrbuf_info->buf_cnt++; + } + } + + return 0; +} + static void rkaiisp_gen_slice_param(struct rkaiisp_device *aidev, struct rkaiisp_model_cfg *model_cfg, int width) { @@ -759,7 +866,7 @@ static void rkaiisp_gen_slice_param(struct rkaiisp_device *aidev, slice_mode[6] << 12 | slice_mode[7] << 14 | slice_num << 24 | - AIISP_MODE_MODE1 << 30; + model_cfg->sw_aiisp_mode << 30; rkaiisp_write(aidev, AIISP_MI_SLICE_CTRL, value, false); lext_num_sel = ext_tab[model_cfg->sw_aiisp_op_mode][slice_mode[slice_num]]; @@ -1000,7 +1107,7 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev, struct rkaiisp_rmsbuf_info *rmsbuf = &aidev->rmsbuf; struct rkaiisp_dummy_buffer *vpsl_buf; dma_addr_t dma_addr; - u32 width, height; + u32 width, height, stride; u32 sig_width = 0; int buffer_index; int i; @@ -1010,6 +1117,7 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev, if (model_cfg->sw_mi_chn_en[i] == 0) continue; + stride = 0; switch (model_cfg->mi_chn_src[i]) { case ISP_IIR: width = CEIL_BY(ispbuf->iir_width, 16); @@ -1022,60 +1130,71 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev, width = ispbuf->raw_width[0]; height = ispbuf->raw_height[0]; dma_addr = vpsl_buf->dma_addr + ispbuf->bnr_buf.u.v35.vpsl_yraw_offs[0]; + stride = ispbuf->bnr_buf.u.v35.vpsl_yraw_stride[0]; break; case VPSL_YRAW_CHN1: width = ispbuf->raw_width[1]; height = ispbuf->raw_height[1]; dma_addr = vpsl_buf->dma_addr + ispbuf->bnr_buf.u.v35.vpsl_yraw_offs[1]; + stride = ispbuf->bnr_buf.u.v35.vpsl_yraw_stride[1]; break; case VPSL_YRAW_CHN2: width = ispbuf->raw_width[2]; height = ispbuf->raw_height[2]; dma_addr = vpsl_buf->dma_addr + ispbuf->bnr_buf.u.v35.vpsl_yraw_offs[2]; + stride = ispbuf->bnr_buf.u.v35.vpsl_yraw_stride[2]; break; case VPSL_YRAW_CHN3: width = ispbuf->raw_width[3]; height = ispbuf->raw_height[3]; dma_addr = vpsl_buf->dma_addr + ispbuf->bnr_buf.u.v35.vpsl_yraw_offs[3]; + stride = ispbuf->bnr_buf.u.v35.vpsl_yraw_stride[3]; break; case VPSL_YRAW_CHN4: width = ispbuf->raw_width[4]; height = ispbuf->raw_height[4]; dma_addr = vpsl_buf->dma_addr + ispbuf->bnr_buf.u.v35.vpsl_yraw_offs[4]; + stride = ispbuf->bnr_buf.u.v35.vpsl_yraw_stride[4]; break; case VPSL_YRAW_CHN5: width = ispbuf->raw_width[5]; height = ispbuf->raw_height[5]; dma_addr = vpsl_buf->dma_addr + ispbuf->bnr_buf.u.v35.vpsl_yraw_offs[5]; + stride = ispbuf->bnr_buf.u.v35.vpsl_yraw_stride[5]; break; case VPSL_SIG_CHN0: width = ispbuf->sig_width[0]; height = ispbuf->sig_height[0]; dma_addr = vpsl_buf->dma_addr + ispbuf->bnr_buf.u.v35.vpsl_sig_offs[0]; + stride = ispbuf->bnr_buf.u.v35.vpsl_sig_stride[0]; sig_width = width; break; case VPSL_SIG_CHN1: width = ispbuf->sig_width[1]; height = ispbuf->sig_height[1]; dma_addr = vpsl_buf->dma_addr + ispbuf->bnr_buf.u.v35.vpsl_sig_offs[1]; + stride = ispbuf->bnr_buf.u.v35.vpsl_sig_stride[1]; sig_width = width; break; case VPSL_SIG_CHN2: width = ispbuf->sig_width[2]; height = ispbuf->sig_height[2]; dma_addr = vpsl_buf->dma_addr + ispbuf->bnr_buf.u.v35.vpsl_sig_offs[2]; + stride = ispbuf->bnr_buf.u.v35.vpsl_sig_stride[2]; sig_width = width; break; case VPSL_SIG_CHN3: width = ispbuf->sig_width[3]; height = ispbuf->sig_height[3]; dma_addr = vpsl_buf->dma_addr + ispbuf->bnr_buf.u.v35.vpsl_sig_offs[3]; + stride = ispbuf->bnr_buf.u.v35.vpsl_sig_stride[3]; sig_width = width; break; case VPSL_SIG_CHN4: width = ispbuf->sig_width[4]; height = ispbuf->sig_height[4]; dma_addr = vpsl_buf->dma_addr + ispbuf->bnr_buf.u.v35.vpsl_sig_offs[4]; + stride = ispbuf->bnr_buf.u.v35.vpsl_sig_stride[4]; sig_width = width; break; case ISP_AIPRE_NARMAP: @@ -1097,7 +1216,8 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev, case VICAP_BAYER_RAW: width = rmsbuf->image_width; height = rmsbuf->image_height; - dma_addr = aidev->rms_inbuf[aidev->curr_idxbuf.airms_st.inbuf_idx].dma_addr; + buffer_index = aidev->curr_idxbuf.airms_st.inbuf_idx; + dma_addr = aidev->rms_inbuf[buffer_index].dma_addr; break; case ALLZERO_SIGMA: width = rmsbuf->sigma_width; @@ -1110,6 +1230,12 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev, height = rmsbuf->narmap_height; dma_addr = aidev->narmap_buf.dma_addr; break; + case ISP_FINAL_Y: + width = ispbuf->iir_width; + height = ispbuf->iir_height; + buffer_index = aidev->curr_idxbuf.aibnr_st.y_src_index; + dma_addr = aidev->ynrinbuf[buffer_index].dma_addr; + break; default: width = 0; height = 0; @@ -1120,12 +1246,15 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev, if (width > 0) { aidev->chn_size[i].width = width; aidev->chn_size[i].height = height; + aidev->chn_size[i].stride = stride; rkaiisp_write(aidev, AIISP_MI_RD_CH0_BASE + 0x100 * i, dma_addr, false); rkaiisp_write(aidev, AIISP_MI_RD_CH0_HEIGHT + 0x100 * i, height, false); v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, - "configure channel %d, width %d, height %d, dma_addr %pad\n", - i, aidev->chn_size[i].width, aidev->chn_size[i].height, &dma_addr); + "configure channel %d, width %d, height %d, stride %d, dma_addr %pad, mi_chn_src %d\n", + i, aidev->chn_size[i].width, aidev->chn_size[i].height, + aidev->chn_size[i].stride, &dma_addr, + model_cfg->mi_chn_src[i]); } } @@ -1147,14 +1276,14 @@ static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx) int buffer_index; int sequence = 0; - if (aidev->exealgo == AIBNR) - sequence = aidev->curr_idxbuf.aibnr_st.sequence; - else if (aidev->exealgo == AIRMS) + if (aidev->exealgo == AIRMS) sequence = aidev->curr_idxbuf.airms_st.sequence; + else + sequence = aidev->curr_idxbuf.aibnr_st.sequence; v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, - "run frame id: %d, run_idx: %d\n", - sequence, run_idx); + "run frame id: %d, run_idx: %d, model_mode %d\n", + sequence, run_idx, aidev->model_mode); cur_params = (struct rkaiisp_params *)aidev->cur_params->vaddr[0]; model_cfg = &cur_params->model_cfg[run_idx]; @@ -1162,7 +1291,38 @@ static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx) lastlv = model_cfg->sw_aiisp_level_num - 1; lv_mode = model_cfg->sw_aiisp_lv_mode[lastlv]; out_chns = channels_lut[model_cfg->sw_aiisp_mode][lv_mode]; - if (aidev->model_mode == REMOSAIC_MODE) { + if (aidev->model_mode == AIYNR_MODE) { + if (run_idx == 0) { + sig_width = rkaiisp_config_rdchannel(aidev, model_cfg, run_idx); + + outbuf_idx = 0; + aidev->outbuf_idx = outbuf_idx; + rkaiisp_write(aidev, AIISP_MI_CHN0_WR_BASE, + aidev->temp_buf[outbuf_idx].dma_addr, false); + + rkaiisp_gen_slice_param(aidev, model_cfg, sig_width); + rkaiisp_determine_size(aidev, model_cfg); + } else if (run_idx < aidev->model_runcnt-1) { + outbuf_idx = aidev->outbuf_idx; + sig_width = rkaiisp_config_rdchannel(aidev, model_cfg, run_idx); + rkaiisp_gen_slice_param(aidev, model_cfg, sig_width); + rkaiisp_determine_size(aidev, model_cfg); + + outbuf_idx = (outbuf_idx + 1) % 2; + aidev->outbuf_idx = outbuf_idx; + rkaiisp_write(aidev, AIISP_MI_CHN0_WR_BASE, + aidev->temp_buf[outbuf_idx].dma_addr, false); + } else { + sig_width = rkaiisp_config_rdchannel(aidev, model_cfg, run_idx); + + buffer_index = aidev->curr_idxbuf.aibnr_st.y_dest_index; + dma_addr = aidev->ynroutbuf[buffer_index].dma_addr; + rkaiisp_write(aidev, AIISP_MI_CHN0_WR_BASE, dma_addr, false); + + rkaiisp_gen_slice_param(aidev, model_cfg, sig_width); + rkaiisp_determine_size(aidev, model_cfg); + } + } else if (aidev->model_mode == REMOSAIC_MODE) { sig_width = rkaiisp_config_rdchannel(aidev, model_cfg, run_idx); dma_addr = aidev->rms_outbuf[aidev->curr_idxbuf.airms_st.outbuf_idx].dma_addr; @@ -1307,10 +1467,10 @@ static int rkaiisp_update_buf(struct rkaiisp_device *aidev) } else { ret = 0; aidev->curr_idxbuf = idxbuf; - if (aidev->exealgo == AIBNR) - sequence = aidev->curr_idxbuf.aibnr_st.sequence; - else if (aidev->exealgo == AIRMS) + if (aidev->exealgo == AIRMS) sequence = aidev->curr_idxbuf.airms_st.sequence; + else + sequence = aidev->curr_idxbuf.aibnr_st.sequence; v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, "idxbuf fifo out: %d\n", sequence); @@ -1401,10 +1561,10 @@ void rkaiisp_trigger(struct rkaiisp_device *aidev) struct rkaiisp_ispbuf_info *ispbuf = &aidev->ispbuf; int sequence = 0; - if (aidev->exealgo == AIBNR) - sequence = aidev->curr_idxbuf.aibnr_st.sequence; - else if (aidev->exealgo == AIRMS) + if (aidev->exealgo == AIRMS) sequence = aidev->curr_idxbuf.airms_st.sequence; + else + sequence = aidev->curr_idxbuf.aibnr_st.sequence; if (!rkaiisp_update_buf(aidev)) { aidev->run_idx = 0; @@ -1425,10 +1585,10 @@ static void rkaiisp_event_queue(struct rkaiisp_device *aidev, union rkaiisp_queu struct v4l2_event event = {0}; int sequence = 0; - if (aidev->exealgo == AIBNR) - sequence = idxbuf->aibnr_st.sequence; - else if (aidev->exealgo == AIRMS) + if (aidev->exealgo == AIRMS) sequence = idxbuf->airms_st.sequence; + else + sequence = idxbuf->aibnr_st.sequence; if (aidev->subdev.is_subs_evt && aidev->exemode != BOTHEVENT_IN_KERNEL) { event.type = RKAIISP_V4L2_EVENT_AIISP_DONE; @@ -1649,6 +1809,9 @@ static long rkaiisp_ioctl_default(struct file *file, void *fh, case RKAIISP_CMD_INIT_AIRMS_BUFPOOL: ret = rkaiisp_init_airms_pool(aidev, arg); break; + case RKAIISP_CMD_GET_YNRBUF_INFO: + ret = rkaiisp_get_ynrbuf_info(aidev, arg); + break; default: ret = -EINVAL; } @@ -1953,3 +2116,54 @@ void rkaiisp_unregister_vdev(struct rkaiisp_device *aidev) vb2_queue_release(vdev->queue); } +int rkaiisp_set_aiynr_ybuf(struct rkaiisp_device *aidev, struct aiisp_aiynr_ybuf_cfg *buf_cfg) +{ + struct rkaiisp_dummy_buffer *ynroutbuf = &aidev->ynroutbuf[0]; + u32 buf_cnt; + int i; + + mutex_lock(&aidev->apilock); + if (aidev->ynr_ybuf_cfg.buf_cnt > 0) + rkaiisp_free_aiynr_ybuf(aidev); + + buf_cnt = buf_cfg->buf_cnt; + if (buf_cnt > RKAIISP_AIYNR_YBUF_NUM_MAX) { + v4l2_err(&aidev->v4l2_dev, + "%s input ynroutbuf cnt(%d) is too big\n", __func__, + buf_cnt); + buf_cnt = RKAIISP_AIYNR_YBUF_NUM_MAX; + } + for (i = 0; i < buf_cnt; i++) { + struct dma_buf_attachment *dba; + struct sg_table *sgt; + + dba = dma_buf_attach(buf_cfg->buf[i], aidev->hw_dev->dev); + if (IS_ERR(dba)) { + mutex_unlock(&aidev->apilock); + return PTR_ERR(dba); + } + + sgt = dma_buf_map_attachment(dba, DMA_BIDIRECTIONAL); + if (IS_ERR(sgt)) { + dma_buf_detach(buf_cfg->buf[i], dba); + mutex_unlock(&aidev->apilock); + return PTR_ERR(sgt); + } + ynroutbuf[i].vaddr = NULL; + ynroutbuf[i].dma_addr = sg_dma_address(sgt->sgl); + get_dma_buf(buf_cfg->buf[i]); + ynroutbuf[i].dmabuf = buf_cfg->buf[i]; + ynroutbuf[i].dba = dba; + ynroutbuf[i].sgt = sgt; + v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, + "%s buf:%pad size:%zu dmabuf:%p\n", __func__, + &ynroutbuf[i].dma_addr, ynroutbuf[i].dmabuf->size, + buf_cfg->buf[i]); + } + + aidev->ynr_ybuf_cfg = *buf_cfg; + mutex_unlock(&aidev->apilock); + + return 0; +} + diff --git a/drivers/media/platform/rockchip/aiisp/aiisp.h b/drivers/media/platform/rockchip/aiisp/aiisp.h index 8c3749b9916f..46b7cec49549 100644 --- a/drivers/media/platform/rockchip/aiisp/aiisp.h +++ b/drivers/media/platform/rockchip/aiisp/aiisp.h @@ -22,6 +22,7 @@ #include #include #include +#include #include "hw.h" #define DRIVER_NAME "rkaiisp" @@ -115,6 +116,7 @@ struct rkaiisp_device { struct rkaiisp_dummy_buffer aiprebuf[RKISP_BUFFER_MAX]; struct rkaiisp_dummy_buffer vpslbuf[RKISP_BUFFER_MAX]; struct rkaiisp_dummy_buffer aiispbuf[RKISP_BUFFER_MAX]; + struct rkaiisp_dummy_buffer ynrinbuf[RKISP_BUFFER_MAX]; struct rkaiisp_dummy_buffer temp_buf[RKAIISP_TMP_BUF_CNT]; u32 outbuf_idx; @@ -124,6 +126,9 @@ struct rkaiisp_device { struct rkaiisp_dummy_buffer sigma_buf; struct rkaiisp_dummy_buffer narmap_buf; + struct aiisp_aiynr_ybuf_cfg ynr_ybuf_cfg; + struct rkaiisp_dummy_buffer ynroutbuf[RKAIISP_AIYNR_YBUF_NUM_MAX]; + struct kfifo idxbuf_kfifo; union rkaiisp_queue_buf curr_idxbuf; @@ -192,8 +197,7 @@ static inline u32 rkaiisp_read(struct rkaiisp_device *aidev, u32 reg, bool is_di } extern struct platform_driver rkaiisp_plat_drv; -int rkaiisp_queue_ispbuf(struct rkaiisp_device *aidev, union rkaiisp_queue_buf *idxbuf); -void rkaiisp_update_list_reg(struct rkaiisp_device *aidev); +int rkaiisp_set_aiynr_ybuf(struct rkaiisp_device *aidev, struct aiisp_aiynr_ybuf_cfg *buf_cfg); void rkaiisp_trigger(struct rkaiisp_device *aidev); int rkaiisp_get_idxbuf_len(struct rkaiisp_device *aidev); enum rkaiisp_irqhdl_ret rkaiisp_irq_hdl(struct rkaiisp_device *aidev, u32 mi_mis); diff --git a/drivers/media/platform/rockchip/aiisp/hw.c b/drivers/media/platform/rockchip/aiisp/hw.c index dfe1675ac805..02d577adae99 100644 --- a/drivers/media/platform/rockchip/aiisp/hw.c +++ b/drivers/media/platform/rockchip/aiisp/hw.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "regs.h" #include "hw.h" @@ -116,11 +117,11 @@ static int rkaiisp_register_irq(struct rkaiisp_hw_dev *hw_dev) return 0; } -int rkaiisp_ispidx_queue(int dev_id, struct rkisp_aiisp_st *idxbuf) +int rkaiisp_cfg_aiynr_yuvbuf(struct aiisp_aiynr_ybuf_cfg *buf_cfg) { struct rkaiisp_hw_dev *hw_dev = rkaiisp_hwdev; struct rkaiisp_device *aidev = NULL; - union rkaiisp_queue_buf queue_buf; + int dev_id; int i; if (!hw_dev) { @@ -128,9 +129,16 @@ int rkaiisp_ispidx_queue(int dev_id, struct rkisp_aiisp_st *idxbuf) return -EINVAL; } + if (!buf_cfg) { + pr_err("Input buf_cfg is NULL!"); + return -EINVAL; + } + + dev_id = buf_cfg->dev_id; for (i = 0; i < hw_dev->dev_num; i++) { if (hw_dev->aidev[i]) { - if ((hw_dev->aidev[i]->is_hw_link) && hw_dev->aidev[i]->dev_id == dev_id) { + if ((hw_dev->aidev[i]->is_hw_link) && + hw_dev->aidev[i]->dev_id == dev_id) { aidev = hw_dev->aidev[i]; break; } @@ -142,15 +150,9 @@ int rkaiisp_ispidx_queue(int dev_id, struct rkisp_aiisp_st *idxbuf) return -EINVAL; } - if (aidev->exemode != BOTHEVENT_TO_AIQ) { - pr_err("aidev %d exemode(%d) is not right!", dev_id, aidev->exemode); - return -EINVAL; - } - - queue_buf.aibnr_st = *idxbuf; - return rkaiisp_queue_ispbuf(aidev, &queue_buf); + return rkaiisp_set_aiynr_ybuf(aidev, buf_cfg); } -EXPORT_SYMBOL(rkaiisp_ispidx_queue); +EXPORT_SYMBOL(rkaiisp_cfg_aiynr_yuvbuf); static const char * const rv1126b_clks[] = { "clk_aiisp_core", diff --git a/include/soc/rockchip/rockchip_aiisp.h b/include/soc/rockchip/rockchip_aiisp.h new file mode 100644 index 000000000000..b5bf6e64b12a --- /dev/null +++ b/include/soc/rockchip/rockchip_aiisp.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ +#ifndef __SOC_ROCKCHIP_AIISP_H +#define __SOC_ROCKCHIP_AIISP_H + +#include +#include + +struct aiisp_aiynr_ybuf_cfg { + int dev_id; + int width; + int height; + u32 buf_cnt; + struct dma_buf *buf[RKAIISP_AIYNR_YBUF_NUM_MAX]; +}; + +#if IS_REACHABLE(CONFIG_VIDEO_ROCKCHIP_AIISP) +int rkaiisp_cfg_aiynr_yuvbuf(struct aiisp_aiynr_ybuf_cfg *buf_cfg); + +#else + +static inline int rkaiisp_cfg_aiynr_yuvbuf(struct aiisp_aiynr_ybuf_cfg *buf_cfg) +{ + return -EINVAL; +} + +#endif +#endif diff --git a/include/uapi/linux/rk-aiisp-config.h b/include/uapi/linux/rk-aiisp-config.h index 54f51202a8c5..6453e62dcc3a 100644 --- a/include/uapi/linux/rk-aiisp-config.h +++ b/include/uapi/linux/rk-aiisp-config.h @@ -10,10 +10,12 @@ #include #define RKAIISP_PYRAMID_LAYER_NUM 4 +#define RKAIISP_AIYNR_LAYER_NUM 5 #define RKAIISP_MAX_RUNCNT 8 #define RKAIISP_MAX_ISPBUF 8 #define RKAIISP_MODEL_UPDATE 0x01 #define RKAIISP_OTHER_UPDATE 0x02 +#define RKAIISP_AIYNR_YBUF_NUM_MAX 8 #define RKAIISP_CMD_SET_PARAM_INFO \ _IOW('V', BASE_VIDIOC_PRIVATE + 0, struct rkaiisp_param_info) @@ -30,6 +32,9 @@ #define RKAIISP_CMD_INIT_AIRMS_BUFPOOL \ _IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct rkaiisp_rmsbuf_info) +#define RKAIISP_CMD_GET_YNRBUF_INFO \ + _IOR('V', BASE_VIDIOC_PRIVATE + 5, struct rkaiisp_ynrbuf_info) + /**********************EVENT_PRIVATE***************************/ #define RKAIISP_V4L2_EVENT_AIISP_DONE (V4L2_EVENT_PRIVATE_START + 1) @@ -50,7 +55,8 @@ enum rkaiisp_chn_src { AIISP_LAST_OUT, VICAP_BAYER_RAW, ALLZERO_SIGMA, - ALLZERO_NARMAP + ALLZERO_NARMAP, + ISP_FINAL_Y }; enum rkaiisp_exealgo { @@ -63,7 +69,8 @@ enum rkaiisp_model_mode { SINGLE_MODE, COMBO_MODE, SINGLEX2_MODE, - REMOSAIC_MODE + REMOSAIC_MODE, + AIYNR_MODE }; enum rkaiisp_exemode { @@ -115,6 +122,13 @@ struct rkaiisp_rmsbuf_info { int outbuf_fd[6]; } __attribute__ ((packed)); +struct rkaiisp_ynrbuf_info { + int width; + int height; + __u32 buf_cnt; + int dma_fd[RKAIISP_AIYNR_YBUF_NUM_MAX]; +} __attribute__ ((packed)); + struct rkaiisp_other_cfg { __u16 sw_neg_noiselimit; __u16 sw_pos_noiselimit; From 34aa1c493ff389a6dd4ecc48e1515178cef1e948 Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Mon, 26 May 2025 16:09:14 +0800 Subject: [PATCH 13/15] media: rockchip: isp: mp output buf notice to aiisp Change-Id: Ic615514cb36aacf33cdaa15976d76265d455e8f9 Signed-off-by: Cai YiWei --- .../media/platform/rockchip/isp/capture_v35.c | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/drivers/media/platform/rockchip/isp/capture_v35.c b/drivers/media/platform/rockchip/isp/capture_v35.c index bd618ec216eb..1c014e65b3cc 100644 --- a/drivers/media/platform/rockchip/isp/capture_v35.c +++ b/drivers/media/platform/rockchip/isp/capture_v35.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "dev.h" #include "regs.h" #include "isp_params_v35.h" @@ -1544,6 +1545,57 @@ static int rkisp_stream_start(struct rkisp_stream *stream) return rkisp_start(stream); } +static int +rkisp_mainpath_buf_to_aiisp(struct rkisp_stream *stream) +{ +#if !IS_REACHABLE(CONFIG_VIDEO_ROCKCHIP_AIISP) + struct rkisp_device *dev = stream->ispdev; + + if (stream->id != RKISP_STREAM_MP || !dev->is_aiisp_yuv) + return 0; + + v4l2_err(&dev->v4l2_dev, + "aiisp is compiled as module, cannot call rkaiisp_cfg_aiynr_yuvbuf\n"); + return -EINVAL; +#else + struct rkisp_device *dev = stream->ispdev; + struct v4l2_rect *isp_out = &dev->isp_sdev.out_crop; + struct v4l2_pix_format_mplane *mp_out = &stream->out_fmt; + struct aiisp_aiynr_ybuf_cfg cfg = { 0 }; + int cnt = 0, ret = -EINVAL; + + if (stream->id != RKISP_STREAM_MP || !dev->is_aiisp_yuv) + return 0; + if (dev->cap_dev.wrap_line) { + v4l2_err(&dev->v4l2_dev, "aiynr no support for wrap\n"); + goto err; + } + if (isp_out->width != mp_out->width || + isp_out->height != mp_out->height) { + v4l2_err(&dev->v4l2_dev, "aiynr no support for mainpath scale\n"); + goto err; + } + cfg.dev_id = dev->dev_id; + cfg.width = mp_out->width; + cfg.height = mp_out->height; + for (cnt = 0; cnt < VIDEO_MAX_FRAME; cnt++) { + if (!stream->dbuf_pool[cnt] || cnt >= RKAIISP_AIYNR_YBUF_NUM_MAX) + break; + cfg.buf[cnt] = stream->dbuf_pool[cnt]; + } + if (cnt) { + cfg.buf_cnt = cnt; + ret = rkaiisp_cfg_aiynr_yuvbuf(&cfg); + if (ret) + v4l2_err(&dev->v4l2_dev, "aiynr yuv buf config error:%d\n", ret); + } else { + v4l2_err(&dev->v4l2_dev, "mainpath no dma buf for aiisp\n"); + } +err: + return ret; +#endif +} + static int rkisp_start_streaming(struct vb2_queue *queue, unsigned int count) { @@ -1616,6 +1668,9 @@ rkisp_start_streaming(struct vb2_queue *queue, unsigned int count) goto buffer_done; } + if (rkisp_mainpath_buf_to_aiisp(stream)) + goto destroy_dummy_buf; + /* enable clocks/power-domains */ ret = dev->pipe.open(&dev->pipe, &node->vdev.entity, true); if (ret < 0) { From 2e3bcaae970e4ed4afb61ff9482d1827b262325d Mon Sep 17 00:00:00 2001 From: hkj Date: Wed, 18 Jun 2025 17:41:38 +0800 Subject: [PATCH 14/15] media: rockchip: aiisp: delete one temp buffer to reduce memory Signed-off-by: hkj Change-Id: I70ac6a2dbd3f0b07244480b9d4e3925a083e009a --- drivers/media/platform/rockchip/aiisp/aiisp.c | 64 +++++++++++++------ drivers/media/platform/rockchip/aiisp/aiisp.h | 5 +- 2 files changed, 48 insertions(+), 21 deletions(-) diff --git a/drivers/media/platform/rockchip/aiisp/aiisp.c b/drivers/media/platform/rockchip/aiisp/aiisp.c index d354c8ea0167..6c37a3069835 100644 --- a/drivers/media/platform/rockchip/aiisp/aiisp.c +++ b/drivers/media/platform/rockchip/aiisp/aiisp.c @@ -397,8 +397,7 @@ static void rkaiisp_free_aiynr_ybuf(struct rkaiisp_device *aidev) static void rkaiisp_free_tempbuf(struct rkaiisp_device *aidev) { - rkaiisp_free_buffer(aidev, &aidev->temp_buf[0]); - rkaiisp_free_buffer(aidev, &aidev->temp_buf[1]); + rkaiisp_free_buffer(aidev, &aidev->temp_buf); } static int rkaiisp_free_pool(struct rkaiisp_device *aidev) @@ -548,6 +547,37 @@ static void rkaiisp_calc_outbuf_size(struct rkaiisp_device *aidev, u32 raw_hgt, } } +static void rkaiisp_set_lastout_buf(struct rkaiisp_device *aidev) +{ + int buffer_index; + + if (aidev->model_mode == REMOSAIC_MODE) { + aidev->lastout_buf[0] = &aidev->temp_buf; + aidev->lastout_buf[1] = &aidev->temp_buf; + return; + } + + if (aidev->model_runcnt % 2 == 0) { + aidev->lastout_buf[0] = &aidev->temp_buf; + if (aidev->model_mode == AIYNR_MODE) { + buffer_index = aidev->curr_idxbuf.aibnr_st.y_dest_index; + aidev->lastout_buf[1] = &aidev->ynroutbuf[buffer_index]; + } else { + buffer_index = aidev->curr_idxbuf.aibnr_st.aiisp_index; + aidev->lastout_buf[1] = &aidev->aiispbuf[buffer_index]; + } + } else { + aidev->lastout_buf[1] = &aidev->temp_buf; + if (aidev->model_mode == AIYNR_MODE) { + buffer_index = aidev->curr_idxbuf.aibnr_st.y_dest_index; + aidev->lastout_buf[0] = &aidev->ynroutbuf[buffer_index]; + } else { + buffer_index = aidev->curr_idxbuf.aibnr_st.aiisp_index; + aidev->lastout_buf[0] = &aidev->aiispbuf[buffer_index]; + } + } +} + static int rkaiisp_init_pool(struct rkaiisp_device *aidev, struct rkaiisp_ispbuf_info *ispbuf) { int i, ret = 0; @@ -611,16 +641,11 @@ static int rkaiisp_init_pool(struct rkaiisp_device *aidev, struct rkaiisp_ispbuf stride = ((ispbuf->iir_width + 1) / 2 * 15 * 11 + 7) >> 3; size = stride * (ispbuf->iir_height + 1) / 2; } - aidev->temp_buf[0].size = size; - aidev->temp_buf[1].size = aidev->temp_buf[0].size; - aidev->temp_buf[0].is_need_vaddr = false; - aidev->temp_buf[0].is_need_dbuf = false; - aidev->temp_buf[0].is_need_dmafd = false; - aidev->temp_buf[1].is_need_vaddr = false; - aidev->temp_buf[1].is_need_dbuf = false; - aidev->temp_buf[1].is_need_dmafd = false; - ret = rkaiisp_allow_buffer(aidev, &aidev->temp_buf[0]); - ret |= rkaiisp_allow_buffer(aidev, &aidev->temp_buf[1]); + aidev->temp_buf.size = size; + aidev->temp_buf.is_need_vaddr = false; + aidev->temp_buf.is_need_dbuf = false; + aidev->temp_buf.is_need_dmafd = false; + ret = rkaiisp_allow_buffer(aidev, &aidev->temp_buf); if (ret) rkaiisp_free_pool(aidev); @@ -1211,7 +1236,7 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev, width = aidev->outbuf_size[aidev->model_runcnt-run_idx].width; height = aidev->outbuf_size[aidev->model_runcnt-run_idx].height; } - dma_addr = aidev->temp_buf[aidev->outbuf_idx].dma_addr; + dma_addr = aidev->lastout_buf[aidev->outbuf_idx]->dma_addr; break; case VICAP_BAYER_RAW: width = rmsbuf->image_width; @@ -1298,7 +1323,7 @@ static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx) outbuf_idx = 0; aidev->outbuf_idx = outbuf_idx; rkaiisp_write(aidev, AIISP_MI_CHN0_WR_BASE, - aidev->temp_buf[outbuf_idx].dma_addr, false); + aidev->lastout_buf[outbuf_idx]->dma_addr, false); rkaiisp_gen_slice_param(aidev, model_cfg, sig_width); rkaiisp_determine_size(aidev, model_cfg); @@ -1311,7 +1336,7 @@ static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx) outbuf_idx = (outbuf_idx + 1) % 2; aidev->outbuf_idx = outbuf_idx; rkaiisp_write(aidev, AIISP_MI_CHN0_WR_BASE, - aidev->temp_buf[outbuf_idx].dma_addr, false); + aidev->lastout_buf[outbuf_idx]->dma_addr, false); } else { sig_width = rkaiisp_config_rdchannel(aidev, model_cfg, run_idx); @@ -1337,7 +1362,7 @@ static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx) outbuf_idx = 0; aidev->outbuf_idx = outbuf_idx; rkaiisp_write(aidev, AIISP_MI_CHN0_WR_BASE, - aidev->temp_buf[outbuf_idx].dma_addr, false); + aidev->lastout_buf[outbuf_idx]->dma_addr, false); rkaiisp_gen_slice_param(aidev, model_cfg, sig_width); rkaiisp_determine_size(aidev, model_cfg); @@ -1350,7 +1375,7 @@ static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx) outbuf_idx = (outbuf_idx + 1) % 2; aidev->outbuf_idx = outbuf_idx; rkaiisp_write(aidev, AIISP_MI_CHN0_WR_BASE, - aidev->temp_buf[outbuf_idx].dma_addr, false); + aidev->lastout_buf[outbuf_idx]->dma_addr, false); } else { sig_width = rkaiisp_config_rdchannel(aidev, model_cfg, run_idx); @@ -1373,7 +1398,7 @@ static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx) outbuf_idx = 0; aidev->outbuf_idx = outbuf_idx; rkaiisp_write(aidev, AIISP_MI_CHN0_WR_BASE, - aidev->temp_buf[outbuf_idx].dma_addr, false); + aidev->lastout_buf[outbuf_idx]->dma_addr, false); rkaiisp_gen_slice_param(aidev, model_cfg, ispbuf->sig_width[3]); rkaiisp_determine_size(aidev, model_cfg); @@ -1389,7 +1414,7 @@ static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx) outbuf_idx = (outbuf_idx + 1) % 2; aidev->outbuf_idx = outbuf_idx; rkaiisp_write(aidev, AIISP_MI_CHN0_WR_BASE, - aidev->temp_buf[outbuf_idx].dma_addr, false); + aidev->lastout_buf[outbuf_idx]->dma_addr, false); } else { rkaiisp_config_rdchannel(aidev, model_cfg, run_idx); @@ -1573,6 +1598,7 @@ void rkaiisp_trigger(struct rkaiisp_device *aidev) aidev->frm_st = ktime_get_ns(); rkaiisp_get_new_iqparam(aidev); rkaiisp_calc_outbuf_size(aidev, ispbuf->iir_height, ispbuf->iir_width); + rkaiisp_set_lastout_buf(aidev); rkaiisp_run_cfg(aidev, aidev->run_idx); aidev->hwstate = HW_RUNNING; rkaiisp_run_start(aidev); diff --git a/drivers/media/platform/rockchip/aiisp/aiisp.h b/drivers/media/platform/rockchip/aiisp/aiisp.h index 46b7cec49549..b45ea78bf38f 100644 --- a/drivers/media/platform/rockchip/aiisp/aiisp.h +++ b/drivers/media/platform/rockchip/aiisp/aiisp.h @@ -31,7 +31,7 @@ #define RKAIISP_V4L2_EVENT_ELEMS 4 #define RKAIISP_MAX_CHANNEL 7 -#define RKAIISP_TMP_BUF_CNT 2 +#define RKAIISP_LASTOUT_BUF_CNT 2 #define RKAIISP_DEFAULT_MAXRUNCNT 8 #define RKAIISP_DEFAULT_PARASIZE (16 * 1024) #define RKAIISP_SW_REG_SIZE 0x3000 @@ -117,7 +117,8 @@ struct rkaiisp_device { struct rkaiisp_dummy_buffer vpslbuf[RKISP_BUFFER_MAX]; struct rkaiisp_dummy_buffer aiispbuf[RKISP_BUFFER_MAX]; struct rkaiisp_dummy_buffer ynrinbuf[RKISP_BUFFER_MAX]; - struct rkaiisp_dummy_buffer temp_buf[RKAIISP_TMP_BUF_CNT]; + struct rkaiisp_dummy_buffer temp_buf; + struct rkaiisp_dummy_buffer *lastout_buf[RKAIISP_LASTOUT_BUF_CNT]; u32 outbuf_idx; struct rkaiisp_rmsbuf_info rmsbuf; From 03ccc5e01f2f4eccd3814d69922e502ec0cd8b2c Mon Sep 17 00:00:00 2001 From: Shengfei Xu Date: Mon, 7 Jul 2025 16:36:27 +0800 Subject: [PATCH 15/15] arm64: dts: rockchip: rv1126bp-evb-v14: Adjust the matching voltage Hardware suggests adjusting the 800mV voltage to 900mV. Signed-off-by: Shengfei Xu Change-Id: Ice645a47138b4905053e8bf6d1a903c616a1c719 --- .../boot/dts/rockchip/rv1126bp-evb-v14.dtsi | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rv1126bp-evb-v14.dtsi b/arch/arm64/boot/dts/rockchip/rv1126bp-evb-v14.dtsi index a7f557374acd..bc001c0a1e30 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126bp-evb-v14.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126bp-evb-v14.dtsi @@ -236,7 +236,6 @@ regulator-name = "vdd_arm"; regulator-state-mem { regulator-off-in-suspend; - regulator-suspend-microvolt = <800000>; }; }; @@ -263,15 +262,15 @@ }; }; - vcc_0v8: LDO_REG1 { + vcc_0v9: LDO_REG1 { regulator-always-on; regulator-boot-on; - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <800000>; - regulator-name = "vcc_0v8"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-name = "vcc_0v9"; regulator-state-mem { regulator-on-in-suspend; - regulator-suspend-microvolt = <800000>; + regulator-suspend-microvolt = <900000>; }; }; @@ -287,15 +286,15 @@ }; }; - vdd0v8_pmu: LDO_REG3 { + vdd0v9_pmu: LDO_REG3 { regulator-always-on; regulator-boot-on; - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <800000>; - regulator-name = "vcc0v8_pmu"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-name = "vcc0v9_pmu"; regulator-state-mem { regulator-on-in-suspend; - regulator-suspend-microvolt = <800000>; + regulator-suspend-microvolt = <900000>; }; };