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>; }; }; 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) 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 2183c8a8d076..d511922e7619 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; } @@ -270,7 +270,7 @@ static int rockchip_dp_loader_protect(struct drm_encoder *encoder, bool on) 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-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..a356d3ffc313 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c @@ -914,13 +914,14 @@ 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); + 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 3abd81a8481b..8d0d3539b0fb 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c @@ -1191,13 +1191,12 @@ 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); + rockchip_drm_panel_loader_protect(dsi2->panel, on); dw_mipi_dsi2_loader_protect(dsi2, on); 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.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index f483df3a32d3..b2541813de9f 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; @@ -1515,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); } @@ -1790,6 +1794,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 665f65181963..8bd377c3fdcd 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 @@ -144,7 +143,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); }; @@ -299,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; @@ -348,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; @@ -580,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; @@ -693,6 +698,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_drm_logo.c b/drivers/gpu/drm/rockchip/rockchip_drm_logo.c index f2cbc73bbd08..8d2e680bcdf0 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_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); diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c index 20d1d9ea1c7a..702f5035ecb7 100644 --- a/drivers/gpu/drm/rockchip/rockchip_lvds.c +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c @@ -431,13 +431,12 @@ 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); + 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 89e48f4f2a4d..de46f441b323 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); @@ -418,7 +417,7 @@ static int rockchip_rgb_encoder_loader_protect(struct drm_encoder *encoder, } if (rgb->panel) - panel_simple_loader_protect(rgb->panel); + rockchip_drm_panel_loader_protect(rgb->panel, on); if (on) { phy_init(rgb->phy); 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(); } diff --git a/drivers/media/platform/rockchip/aiisp/aiisp.c b/drivers/media/platform/rockchip/aiisp/aiisp.c index 8ae4ffbe429a..6c37a3069835 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,10 +365,39 @@ 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]); - rkaiisp_free_buffer(aidev, &aidev->temp_buf[1]); + rkaiisp_free_buffer(aidev, &aidev->temp_buf); } static int rkaiisp_free_pool(struct rkaiisp_device *aidev) @@ -394,7 +423,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 +467,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 +482,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) { @@ -491,10 +547,41 @@ 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; - 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,18 +623,29 @@ 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; - 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]); + 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.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); @@ -635,7 +733,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 +754,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 +774,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 +891,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 +1132,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 +1142,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 +1155,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: @@ -1092,12 +1236,13 @@ 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; 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 +1255,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 +1271,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 +1301,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 +1316,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->lastout_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->lastout_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; @@ -1177,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); @@ -1190,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); @@ -1213,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); @@ -1229,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); @@ -1307,10 +1492,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 +1586,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; @@ -1413,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); @@ -1425,10 +1611,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 +1835,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 +2142,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..b45ea78bf38f 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" @@ -30,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 @@ -115,7 +116,9 @@ 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 temp_buf[RKAIISP_TMP_BUF_CNT]; + struct rkaiisp_dummy_buffer ynrinbuf[RKISP_BUFFER_MAX]; + struct rkaiisp_dummy_buffer temp_buf; + struct rkaiisp_dummy_buffer *lastout_buf[RKAIISP_LASTOUT_BUF_CNT]; u32 outbuf_idx; struct rkaiisp_rmsbuf_info rmsbuf; @@ -124,6 +127,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 +198,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/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..1c014e65b3cc 100644 --- a/drivers/media/platform/rockchip/isp/capture_v35.c +++ b/drivers/media/platform/rockchip/isp/capture_v35.c @@ -10,8 +10,10 @@ #include #include #include +#include #include "dev.h" #include "regs.h" +#include "isp_params_v35.h" /* ISP35 * |-->mainpath------------------->ddr @@ -726,12 +728,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 +813,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 +838,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 +940,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 +971,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 +989,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 +1017,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 +1047,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 +1140,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 +1168,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 +1324,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 +1365,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 +1416,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 +1442,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); @@ -1471,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) { @@ -1543,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) { @@ -1635,6 +1763,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.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/dev.h b/drivers/media/platform/rockchip/isp/dev.h index 1dafd16c183d..c641eba2e9ac 100644 --- a/drivers/media/platform/rockchip/isp/dev.h +++ b/drivers/media/platform/rockchip/isp/dev.h @@ -311,7 +311,10 @@ 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; bool is_multi_one_sync; bool is_wait_aiq; @@ -321,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 9d7b1d657920..efbf9221835a 100644 --- a/drivers/media/platform/rockchip/isp/isp_params.c +++ b/drivers/media/platform/rockchip/isp/isp_params.c @@ -311,6 +311,11 @@ 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->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 177b5f600f34..9b2a84b44c8e 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); } @@ -4458,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 | @@ -4474,7 +4476,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++) { @@ -4524,22 +4526,31 @@ 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; 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); 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) { - vpsl_update_buf(params_vdev); - if (!priv->yraw_sel) + 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_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 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; @@ -5305,6 +5316,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 +5514,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 +5693,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; @@ -5938,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); @@ -5984,12 +6046,14 @@ 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; 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"); @@ -6002,6 +6066,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 +6083,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 +6119,23 @@ 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; } + is_event_queue = false; } - 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 +6143,15 @@ 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); } + 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)\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 @@ -6090,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", @@ -6109,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]; @@ -6173,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", @@ -6211,6 +6291,107 @@ 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); + + 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; + 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; + if (IS_HDR_RDBK(dev->rd_mode)) { + dev->is_first_frame = true; + dev->irq_ends_mask = ISP_FRAME_BNR | ISP_FRAME_VPSL; + } + } +} + static void rkisp_params_isr_v35(struct rkisp_isp_params_vdev *params_vdev, u32 isp_mis) { @@ -6224,7 +6405,8 @@ 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; priv->bay3d_iir_idx = i; @@ -6271,6 +6453,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 && !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; + 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 && !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; + 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 +6505,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 +6514,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); @@ -6344,6 +6544,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_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..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; @@ -159,7 +160,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/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 6984ca43282e..27ca6de91a6b 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); @@ -1017,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); @@ -1158,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); @@ -1358,11 +1360,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) { @@ -1393,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 @@ -1427,6 +1432,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 +1477,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 +1990,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 +2095,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 */ @@ -2134,7 +2140,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,23 +3958,53 @@ 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; + /* init aiisp stop */ + 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 { + 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; } - 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->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; @@ -3982,6 +4018,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); @@ -3989,21 +4026,40 @@ 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, 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); - dev->is_aiisp_en = !!cfg->mode; + if (!(dev->isp_state & ISP_START)) { + 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, @@ -4087,7 +4143,19 @@ 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_en) + 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 && !dev->is_aiisp_stop) return -EINVAL; spin_lock_irqsave(&dev->rdbk_lock, lock_flags); @@ -4115,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; @@ -4262,7 +4331,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; @@ -5255,10 +5324,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) { 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); 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) 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); 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; 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;