Merge commit '03ccc5e01f2f4eccd3814d69922e502ec0cd8b2c'

* commit '03ccc5e01f2f4eccd3814d69922e502ec0cd8b2c':
  arm64: dts: rockchip: rv1126bp-evb-v14: Adjust the matching voltage
  media: rockchip: aiisp: delete one temp buffer to reduce memory
  media: rockchip: isp: mp output buf notice to aiisp
  media: rockchip: aiisp: modify for aiynr algo
  rtc: rockchip: add ready flag for rtc setting time
  soc: rockchip: cpuinfo: export chip unique id to userspace
  media: rockchip: vpss: offline mode support auto unite output
  drm/rockchip: vop2: Add "DIMMING_DATA" property for local dimming
  media: rockchip: isp: aiisp switch for offline mode
  media: rockchip: isp: aiisp switch for isp35
  media: rockchip: isp: support aiisp yuv mode
  input: touchscreen: gt1x: prefix global variables and functions with "gt1x_"
  MALI: valhall: add gpu mem sysfs entry
  drm/rockchip: Make the DRM panel as part of Rockchip DRM sub devices for panel loader protect
  drm/rockchip: Pass struct rockchip_drm_sub_dev for &rockchip_drm_sub_dev.loader_protect()

Change-Id: I61809a96152857eb7f0728a6fe49af919bf0fbbb
This commit is contained in:
Tao Huang
2025-07-07 18:53:19 +08:00
47 changed files with 1372 additions and 326 deletions

View File

@@ -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>;
};
};

View File

@@ -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.

View File

@@ -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);
}

View File

@@ -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)

View File

@@ -45,7 +45,7 @@
#include <drm/drm_panel.h>
#include <drm/display/drm_dsc.h>
#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);

View File

@@ -1,19 +0,0 @@
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
/*
* Copyright (c) 2021 Rockchip Electronics Co., Ltd.
* Author: Sandy Huang <hjc@rock-chips.com>
*/
#ifndef PANEL_SIMPLE_H
#define PANEL_SIMPLE_H
#include <drm/drm_panel.h>
#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

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -15,6 +15,7 @@
#include <drm/drm_fourcc.h>
#include <drm/drm_edid.h>
#include <drm/drm_gem.h>
#include <drm/drm_panel.h>
#include <drm/rockchip_drm.h>
#include <linux/media-bus-format.h>
@@ -23,8 +24,6 @@
#include <soc/rockchip/rockchip_dmc.h>
#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,

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);*/

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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, &gt1x_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 &gt1x_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();
}

View File

@@ -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;
}

View File

@@ -22,6 +22,7 @@
#include <media/v4l2-ioctl.h>
#include <media/videobuf2-core.h>
#include <media/v4l2-event.h>
#include <soc/rockchip/rockchip_aiisp.h>
#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);

View File

@@ -21,6 +21,7 @@
#include <media/videobuf2-cma-sg.h>
#include <media/videobuf2-dma-sg.h>
#include <soc/rockchip/rockchip_iommu.h>
#include <soc/rockchip/rockchip_aiisp.h>
#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",

View File

@@ -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;

View File

@@ -10,8 +10,10 @@
#include <media/v4l2-subdev.h>
#include <media/videobuf2-dma-contig.h>
#include <media/videobuf2-dma-sg.h>
#include <soc/rockchip/rockchip_aiisp.h>
#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;

View File

@@ -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;
};

View File

@@ -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:

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);
};
/*

View File

@@ -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(&params_vdev->config_lock, flags);
while (!list_empty(&params_vdev->params_be)) {
params_buf = list_first_entry(&params_vdev->params_be, struct rkisp_buffer, queue);
list_del(&params_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(&params_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
}
spin_unlock_irqrestore(&params_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)

View File

@@ -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];

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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) {

View File

@@ -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)

View File

@@ -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);

View File

@@ -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)

View File

@@ -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);

View File

@@ -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 <linux/dma-buf.h>
#include <linux/rk-aiisp-config.h>
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

View File

@@ -10,10 +10,12 @@
#include <linux/rk-isp2-config.h>
#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;

View File

@@ -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;