[PATCH v2 05/13] media: platform: mediatek: add isp_7x seninf unit
CK Hu (胡俊光)
ck.hu at mediatek.com
Wed Jul 16 04:06:31 UTC 2025
On Mon, 2025-07-07 at 09:31 +0800, shangyao lin wrote:
> From: "shangyao.lin" <shangyao.lin at mediatek.com>
>
> Introduce support for the MediaTek sensor interface (seninf) in the SoC camera
> subsystem, focusing on CSI and stream control. The driver manages parameter
> control, metering, status tracking, and interrupt handling for the camera sensor
> interface hardware. It integrates with the MediaTek ISP CAMSYS, bridging camera
> sensors and the ISP system, and provides V4L2 framework support for dynamic
> stream configuration and virtual channel management.
>
> ---
[snip]
> .../isp_7x/camsys/kd_imgsensor_define_v4l2.h | 86 +
> .../isp/isp_7x/camsys/mtk_cam-seninf-def.h | 237 ++
> .../isp/isp_7x/camsys/mtk_cam-seninf-drv.c | 1441 ++++++++++++
> .../isp/isp_7x/camsys/mtk_cam-seninf-drv.h | 16 +
> .../isp/isp_7x/camsys/mtk_cam-seninf-hw.h | 108 +
> .../isp/isp_7x/camsys/mtk_cam-seninf-if.h | 24 +
> .../isp/isp_7x/camsys/mtk_cam-seninf-regs.h | 44 +
> .../isp/isp_7x/camsys/mtk_cam-seninf-route.c | 279 +++
> .../isp/isp_7x/camsys/mtk_cam-seninf-route.h | 20 +
> .../isp/isp_7x/camsys/mtk_cam-seninf.h | 161 ++
Add Makefile to build mtk-cam-seninfo-xxx.c in this patch.
Make this patch could be built.
> .../isp_7x/camsys/mtk_csi_phy_2_0/Makefile | 5 +
> .../mtk_csi_phy_2_0/mtk_cam-seninf-cammux.h | 679 ++++++
> .../mtk_cam-seninf-csi0-cphy.h | 51 +
> .../mtk_cam-seninf-csi0-dphy.h | 98 +
> .../mtk_cam-seninf-hw_phy_2_0.c | 1932 +++++++++++++++++
> .../mtk_cam-seninf-mipi-rx-ana-cdphy-csi0a.h | 165 ++
> .../mtk_cam-seninf-seninf1-csi2.h | 264 +++
> .../mtk_cam-seninf-seninf1-mux.h | 120 +
> .../mtk_csi_phy_2_0/mtk_cam-seninf-seninf1.h | 46 +
> .../mtk_csi_phy_2_0/mtk_cam-seninf-tg1.h | 43 +
> .../mtk_csi_phy_2_0/mtk_cam-seninf-top-ctrl.h | 76 +
> 21 files changed, 5895 insertions(+)
> create mode 100755 drivers/media/platform/mediatek/isp/isp_7x/camsys/kd_imgsensor_define_v4l2.h
> create mode 100755 drivers/media/platform/mediatek/isp/isp_7x/camsys/mtk_cam-seninf-def.h
> create mode 100755 drivers/media/platform/mediatek/isp/isp_7x/camsys/mtk_cam-seninf-drv.c
> create mode 100755 drivers/media/platform/mediatek/isp/isp_7x/camsys/mtk_cam-seninf-drv.h
> create mode 100755 drivers/media/platform/mediatek/isp/isp_7x/camsys/mtk_cam-seninf-hw.h
> create mode 100755 drivers/media/platform/mediatek/isp/isp_7x/camsys/mtk_cam-seninf-if.h
> create mode 100755 drivers/media/platform/mediatek/isp/isp_7x/camsys/mtk_cam-seninf-regs.h
> create mode 100755 drivers/media/platform/mediatek/isp/isp_7x/camsys/mtk_cam-seninf-route.c
> create mode 100755 drivers/media/platform/mediatek/isp/isp_7x/camsys/mtk_cam-seninf-route.h
> create mode 100755 drivers/media/platform/mediatek/isp/isp_7x/camsys/mtk_cam-seninf.h
> create mode 100755 drivers/media/platform/mediatek/isp/isp_7x/camsys/mtk_csi_phy_2_0/Makefile
> create mode 100755 drivers/media/platform/mediatek/isp/isp_7x/camsys/mtk_csi_phy_2_0/mtk_cam-seninf-cammux.h
> create mode 100755 drivers/media/platform/mediatek/isp/isp_7x/camsys/mtk_csi_phy_2_0/mtk_cam-seninf-csi0-cphy.h
> create mode 100755 drivers/media/platform/mediatek/isp/isp_7x/camsys/mtk_csi_phy_2_0/mtk_cam-seninf-csi0-dphy.h
> create mode 100755 drivers/media/platform/mediatek/isp/isp_7x/camsys/mtk_csi_phy_2_0/mtk_cam-seninf-hw_phy_2_0.c
> create mode 100755 drivers/media/platform/mediatek/isp/isp_7x/camsys/mtk_csi_phy_2_0/mtk_cam-seninf-mipi-rx-ana-cdphy-csi0a.h
> create mode 100755 drivers/media/platform/mediatek/isp/isp_7x/camsys/mtk_csi_phy_2_0/mtk_cam-seninf-seninf1-csi2.h
> create mode 100755 drivers/media/platform/mediatek/isp/isp_7x/camsys/mtk_csi_phy_2_0/mtk_cam-seninf-seninf1-mux.h
> create mode 100755 drivers/media/platform/mediatek/isp/isp_7x/camsys/mtk_csi_phy_2_0/mtk_cam-seninf-seninf1.h
> create mode 100755 drivers/media/platform/mediatek/isp/isp_7x/camsys/mtk_csi_phy_2_0/mtk_cam-seninf-tg1.h
> create mode 100755 drivers/media/platform/mediatek/isp/isp_7x/camsys/mtk_csi_phy_2_0/mtk_cam-seninf-top-ctrl.h
>
> diff --git a/drivers/media/platform/mediatek/isp/isp_7x/camsys/kd_imgsensor_define_v4l2.h b/drivers/media/platform/mediatek/isp/isp_7x/camsys/kd_imgsensor_define_v4l2.h
> new file mode 100755
> index 000000000000..54c23afe64bd
> --- /dev/null
> +++ b/drivers/media/platform/mediatek/isp/isp_7x/camsys/kd_imgsensor_define_v4l2.h
> @@ -0,0 +1,86 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2019 MediaTek Inc.
> + */
> +
> +#ifndef _KD_IMGSENSOR_DATA_V4L2_H
> +#define _KD_IMGSENSOR_DATA_V4L2_H
> +
> +enum VC_FEATURE {
Because mtk_cam_seninf_get_vc_feature() is useless, so VC_FEATURE is useless.
Drop these.
> + VC_NONE = 0,
> + VC_MIN_NUM,
> + VC_RAW_DATA = VC_MIN_NUM,
> + VC_RAW_DATA_MAX,
> +
> + VC_PDAF_MIN_NUM = VC_RAW_DATA_MAX,
> + VC_PDAF_STATS = VC_PDAF_MIN_NUM,
> + VC_PDAF_STATS_NE,
> + VC_PDAF_STATS_ME,
> + VC_PDAF_STATS_SE,
> + VC_PDAF_STATS_PIX_1,
> + VC_PDAF_STATS_PIX_2,
> + VC_PDAF_STATS_NE_PIX_1 = VC_PDAF_STATS_PIX_1,
> + VC_PDAF_STATS_NE_PIX_2 = VC_PDAF_STATS_PIX_2,
> + VC_PDAF_STATS_ME_PIX_1,
> + VC_PDAF_STATS_ME_PIX_2,
> + VC_PDAF_STATS_SE_PIX_2,
> + VC_PDAF_MAX_NUM,
> +
> + VC_HDR_MIN_NUM = VC_PDAF_MAX_NUM,
> + VC_HDR_MVHDR = VC_HDR_MIN_NUM,
> + VC_HDR_MAX_NUM,
> +
> + VC_3HDR_MIN_NUM = VC_HDR_MAX_NUM,
> + VC_3HDR_EMBEDDED = VC_3HDR_MIN_NUM,
> + VC_3HDR_FLICKER,
> + VC_3HDR_Y,
> + VC_3HDR_AE,
> + VC_3HDR_MAX_NUM,
> +
> + VC_STAGGER_MIN_NUM = VC_3HDR_MAX_NUM,
> + VC_STAGGER_EMBEDDED = VC_STAGGER_MIN_NUM,
> + VC_STAGGER_NE,
> + VC_STAGGER_ME,
> + VC_STAGGER_SE,
> + VC_STAGGER_MAX_NUM,
> +
> + VC_YUV_MIN_NUM = VC_STAGGER_MAX_NUM,
> + VC_YUV_Y = VC_YUV_MIN_NUM,
> + VC_YUV_UV,
> + VC_YUV_MAX_NUM,
> +
> + VC_RAW_EXT_MIN_NUM = VC_YUV_MAX_NUM,
> + VC_RAW_W_DATA = VC_RAW_EXT_MIN_NUM,
> + VC_RAW_PROCESSED_DATA,
> + VC_RAW_EXT_MAX_NUM,
> +
> + VC_GENERAL_DATA_MIN_NUM = VC_RAW_EXT_MAX_NUM,
> + VC_GENERAL_EMBEDDED = VC_GENERAL_DATA_MIN_NUM,
> + VC_GENERAL_DATA_MAX_NUM,
> +
> + VC_MAX_NUM = VC_GENERAL_DATA_MAX_NUM,
> +};
> +
[snip]
> +
> +#endif /* _KD_IMGSENSOR_DATA_H */
> diff --git a/drivers/media/platform/mediatek/isp/isp_7x/camsys/mtk_cam-seninf-def.h b/drivers/media/platform/mediatek/isp/isp_7x/camsys/mtk_cam-seninf-def.h
> new file mode 100755
> index 000000000000..39f6005c8227
> --- /dev/null
> +++ b/drivers/media/platform/mediatek/isp/isp_7x/camsys/mtk_cam-seninf-def.h
> @@ -0,0 +1,237 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +// Copyright (c) 2022 MediaTek Inc.
> +
> +#ifndef __MTK_CAM_SENINF_DEF_H__
> +#define __MTK_CAM_SENINF_DEF_H__
> +
> +#include <linux/bitfield.h>
> +
> +#define SENINF_VC_MAXCNT 8
> +#define SENINF_DEF_PIXEL_MODE 2
> +
> +#define SENINF_CLK_MARGIN_IN_PERCENT 0
> +#define HW_BUF_EFFECT 10
> +
> +#define SENINF_HS_TRAIL_EN_CONDITION 1450000000
SENINF_HS_TRAIL_EN_CONDITION is useless. Drop it.
> +#define SENINF_TIMESTAMP_CLK 1000
SENINF_TIMESTAMP_CLK is useless. Drop it.
> +#define ISP_CLK_LOW 273000000
> +
> +#define SENINF_CPHY_SETTLE_DELAY_DT 0x10
> +#define SENINF_DPHY_SETTLE_DELAY_DT 0x10
> +#define SENINF_SETTLE_DELAY_CK 0x11
> +#define SENINF_HS_TRAIL_PARAMETER 0x34
> +
> +#define SENSOR_CLOCK_POLARITY_HIGH 0
SENSOR_CLOCK_POLARITY_HIGH is useless. Drop it.
> +#define SENSOR_CLOCK_POLARITY_LOW 1
SENSOR_CLOCK_POLARITY_LOW is useless. Drop it.
> +#define NUM_PORTS 2
NUM_PORTS is useless. Drop it.
> +#define DEFAULT_WIDTH 1600
> +#define DEFAULT_HEIGHT 1200
> +#define CSI_PORT_A_MASK GENMASK(3, 1)
> +#define SENINF_MAX_STREAM 7
> +
[snip]
> +
> +enum SENINF_PHY_VER_ENUM {
> + SENINF_PHY_2_0,
> + SENINF_PHY_VER_NUM,
> +};
SENINF_PHY_VER_ENUM, SENINF_PHY_2_0 and SENINF_PHY_VER_NUM are useless.
Drop them.
> +
> +#define MTK_CSI_PHY_VERSIONS "mtk_csi_phy_2_0"
> +
[snip]
> +
> +static const char * const csi_port_names[] = {
> + SENINF_CSI_PORT_NAMES
Drop SENINF_CSI_PORT_NAMES and place string here.
> +};
> +
> +static const char * const clk_names[] = {
> + SENINF_CLK_NAMES
Drop SENINF_CLK_NAMES and place string here.
> +};
> +
> +static const char * const set_reg_names[] = {
> + SET_REG_KEYS_NAMES
Drop SET_REG_KEYS_NAMES and place string here.
> +};
> +
> +enum REG_OPS_CMD {
> + REG_OPS_CMD_ID,
> + REG_OPS_CMD_CSI,
> + REG_OPS_CMD_RG,
> + REG_OPS_CMD_VAL,
> + REG_OPS_CMD_MAX_NUM,
> +};
REG_OPS_CMD_XXX is not defined. Drop all of them.
> +
[snip]
> +
> +static int seninf_core_probe(struct platform_device *pdev)
> +{
> + int i, ret, irq;
> + struct resource *res;
> + struct seninf_core *core;
> + struct device *dev = &pdev->dev;
> +
> + core = devm_kzalloc(&pdev->dev, sizeof(*core), GFP_KERNEL);
> + if (!core)
> + return -ENOMEM;
> +
> + dev_set_drvdata(dev, core);
> + core->dev = dev;
> + mutex_init(&core->mutex);
> + INIT_LIST_HEAD(&core->list);
> +
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "base");
> + core->reg_if = devm_ioremap_resource(dev, res);
> + if (IS_ERR(core->reg_if))
> + return PTR_ERR(core->reg_if);
> +
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ana-rx");
"ana-rx" is not defined in binding document. Drop this.
> + core->reg_ana = devm_ioremap_resource(dev, res);
> + if (IS_ERR(core->reg_ana))
> + return PTR_ERR(core->reg_ana);
> +
> + ret = get_seninf_cfg(dev, core);
> + if (ret) {
> + dev_err(dev, "failed to get seninf ops\n");
> + return ret;
> + }
> + mtk_cam_seninf_init_res(core);
> +
> + spin_lock_init(&core->spinlock_irq);
> + irq = platform_get_irq(pdev, 0);
> + if (!irq) {
> + dev_err(dev, "failed to get irq\n");
> + return -ENODEV;
> + }
> +
> + ret = devm_request_irq(dev, irq, mtk_irq_seninf, 0,
> + dev_name(dev), core);
> + if (ret) {
> + dev_err(dev, "failed to request irq=%d\n", irq);
> + return ret;
> + }
> +
> + /* default platform properties */
> + core->cphy_settle_delay_dt = SENINF_CPHY_SETTLE_DELAY_DT;
> + core->dphy_settle_delay_dt = SENINF_DPHY_SETTLE_DELAY_DT;
> + core->settle_delay_ck = SENINF_SETTLE_DELAY_CK;
> + core->hs_trail_parameter = SENINF_HS_TRAIL_PARAMETER;
> +
> + /* read platform properties from device tree */
> + of_property_read_u32(dev->of_node, "cphy_settle_delay_dt",
> + &core->cphy_settle_delay_dt);
"cphy_settle_delay_dt" is not defined in binding document. Drop this.
> + of_property_read_u32(dev->of_node, "dphy_settle_delay_dt",
> + &core->dphy_settle_delay_dt);
"dphy_settle_delay_dt" is not defined in binding document. Drop this.
> + of_property_read_u32(dev->of_node, "settle_delay_ck",
> + &core->settle_delay_ck);
"settle_delay_ck" is not defined in binding document. Drop this.
> + of_property_read_u32(dev->of_node, "hs_trail_parameter",
> + &core->hs_trail_parameter);
"hs_trail_parameter" is not defined in binding document. Drop this.
> +
> + core->dfs.cnt = 0;
> + core->dfs.reg = NULL;
> +
> + ret = seninf_core_pm_runtime_enable(core);
> + if (ret) {
> + dev_info(dev, "failed to enable seninf_core_pm_runtime\n");
> + return ret;
> + }
> +
> + for (i = 0; i < CLK_MAXCNT; i++) {
> + core->clk[i] = devm_clk_get(dev, clk_names[i]);
> + if (IS_ERR(core->clk[i])) {
> + dev_info(dev, "failed to get %s\n", clk_names[i]);
> + core->clk[i] = NULL;
> + /* ignore not define seninf */
> + }
> + }
> +
> + ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
It seems "mediatek,mt8188-seninf-core" would probe "mediatek,mt8188-seninf",
but I does not find any relation between them.
How "mediatek,mt8188-seninf-core" proble "mediatek,mt8188-seninf"?
> + if (ret) {
> + dev_info(dev, "%s: failed to create sub devices\n", __func__);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
[snip]
> +
> +int update_isp_clk(struct seninf_ctx *ctx)
> +{
> + int i, pixelmode;
> + struct seninf_dfs *dfs = &ctx->core->dfs;
> + s64 pixel_rate = -1;
> + u64 dfs_freq;
> + struct seninf_vc *vc;
> + int ret = 0;
> +
> + if (!dfs->cnt) {
dfs->cnt is always zero, so drop dfs and drop this function.
> + dev_info(ctx->dev, "dfs not ready.\n");
> + return ret;
> + }
> +
> + vc = mtk_cam_seninf_get_vc_by_pad(ctx, PAD_SRC_RAW0);
> + if (!vc) {
> + dev_info(ctx->dev, "failed to get vc\n");
> + return -1;
> + }
> + dev_info(ctx->dev,
> + "%s dfs->cnt %d pixel mode %d customized_pixel_rate %lld, buffered_pixel_rate %lld mipi_pixel_rate %lld\n",
> + __func__, dfs->cnt, vc->pixel_mode, ctx->customized_pixel_rate,
> + ctx->buffered_pixel_rate, ctx->mipi_pixel_rate);
> +
> + /* Use SensorPixelrate */
> + if (ctx->customized_pixel_rate) {
> + pixel_rate = ctx->customized_pixel_rate;
> + } else if (ctx->buffered_pixel_rate) {
> + pixel_rate = ctx->buffered_pixel_rate;
> + } else if (ctx->mipi_pixel_rate) {
> + pixel_rate = ctx->mipi_pixel_rate;
> + } else {
> + dev_info(ctx->dev, "failed to get pixel_rate\n");
> + return -EINVAL;
> + }
> +
> + pixelmode = vc->pixel_mode;
> + for (i = 0; i < dfs->cnt; i++) {
> + dfs_freq = dfs->freqs[i];
> + dfs_freq = dfs_freq * (100 - SENINF_CLK_MARGIN_IN_PERCENT);
> + do_div(dfs_freq, 100);
> + if ((dfs_freq << pixelmode) >= pixel_rate)
> + break;
> + }
> +
> + if (i == dfs->cnt) {
> + dev_info(ctx->dev, "mux is overrun. please adjust pixelmode\n");
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
[snip]
> +
> +int mtk_cam_seninf_calc_pixelrate(struct device *dev, s64 width, s64 height,
> + s64 hblank, s64 vblank,
> + int fps_n, int fps_d,
> + s64 sensor_pixel_rate)
> +{
> + int ret;
> + s64 p_pixel_rate = sensor_pixel_rate;
> +
> + ret = calc_buffered_pixel_rate(dev, width, height, hblank, vblank,
> + fps_n, fps_d, &p_pixel_rate);
> + if (ret)
> + return sensor_pixel_rate;
> +
> + return p_pixel_rate;
> +}
> +
> +int mtk_cam_seninf_dump(struct v4l2_subdev *sd)
This function does nothing. Drop it.
> +{
> + int ret = 0;
> + //TODO debug patch
> + return ret;
> +}
> +
> +void mtk_cam_seninf_set_secure(struct v4l2_subdev *sd,
> + int enable, unsigned int sec_info_addr)
This function is useless. Drop it.
> +{
> + struct seninf_ctx *ctx = sd_to_ctx(sd);
> +
> + ctx->sec_info_addr = sec_info_addr;
> + dev_info(ctx->dev, "[%s]: %x, enable: %d\n",
> + __func__, sec_info_addr, enable);
> + ctx->is_secure = enable ? 1 : 0;
> +}
>
[snip]
> +
> +enum SET_REG_KEYS {
> + REG_KEY_MIN = 0,
> + REG_KEY_SETTLE_CK = REG_KEY_MIN,
> + REG_KEY_SETTLE_DT,
> + REG_KEY_HS_TRAIL_EN,
> + REG_KEY_HS_TRAIL_PARAM,
> + REG_KEY_CSI_IRQ_STAT,
> + REG_KEY_CSI_RESYNC_CYCLE,
> + REG_KEY_MUX_IRQ_STAT,
> + REG_KEY_CAMMUX_IRQ_STAT,
> + REG_KEY_CAMMUX_VSYNC_IRQ_EN,
> + REG_KEY_CSI_IRQ_EN,
> + REG_KEY_MAX_NUM
Because mtk_cam_seninf_set_reg() is useless and drop,
these enum is also useless. Drop these.
> +};
> +
> +#define SET_REG_KEYS_NAMES \
> + "RG_SETTLE_CK", \
> + "RG_SETTLE_DT", \
> + "RG_HS_TRAIL_EN", \
> + "RG_HS_TRAIL_PARAM", \
> + "RG_CSI_IRQ_STAT", \
> + "RG_CSI_RESYNC_CYCLE", \
> + "RG_MUX_IRQ_STAT", \
> + "RG_CAMMUX_IRQ_STAT", \
> + "REG_VSYNC_IRQ_EN", \
> + "RG_CSI_IRQ_EN", \
> +
> +struct mtk_cam_seninf_mux_meter {
mtk_cam_seninf_mux_meter is useless. Drop it.
> + u32 width;
> + u32 height;
> + u32 h_valid;
> + u32 h_blank;
> + u32 v_valid;
> + u32 v_blank;
> + s64 mipi_pixel_rate;
> + s64 vb_in_us;
> + s64 hb_in_us;
> + s64 line_time_in_us;
> +};
> +
[snip]
> +
> +#define to_std_fmt_code(code) \
> + ((code) & 0xFFFF)
to_std_fmt_code() is not necessary. Drop it.
> +
> +
[snip]
> +
> +void mtk_cam_seninf_mux_put(struct seninf_ctx *ctx, struct seninf_mux *mux)
> +{
> + struct seninf_core *core = ctx->core;
> +
> + mutex_lock(&core->mutex);
> + list_move_tail(&mux->list, &core->list_mux);
> + mutex_unlock(&core->mutex);
> +}
I think using list to manage mux resource is a little over coding.
An array could be more simple.
struct sensor_core {
...
bool *mux_used;
...
};
void mtk_cam_seninf_init_res(struct seninf_core *core)
{
int i;
core->mux_used = kzalloc(g_seninf_cfg->mux_num * sizeof(*core->mux_used));
}
int mtk_cam_seninf_mux_get_pref(struct seninf_ctx *ctx,
int pref_cnt)
{
int mux;
mutex_lock(&core->mutex);
if (!core->mux_used[pref_cnt]) {
core->mux_used[pref_cnt] = true;
mutex_unlock(&core->mutex);
return pref_cnt;
}
for (mux = 0; mux < g_seninf_cfg->mux_num; mux++)
if (!core->mux_used[mux]) {
core->mux_used[mux] = true;
mutex_unlock(&core->mutex);
return mux
}
mutex_unlock(&core->mutex);
return -1;
}
void mtk_cam_seninf_release_mux(struct seninf_ctx *ctx)
{
int mux;
mutex_lock(&core->mutex);
for (mux = 0; mux < g_seninf_cfg->mux_num; mux++)
core->mux_used[mux] = false;
mutex_unlock(&core->mutex);
}
> +
> +struct seninf_vc *mtk_cam_seninf_get_vc_by_pad(struct seninf_ctx *ctx, int idx)
> +{
> + int i;
> + struct seninf_vcinfo *vcinfo = &ctx->vcinfo;
> +
> + for (i = 0; i < vcinfo->cnt; i++) {
> + if (vcinfo->vc[i].out_pad == idx)
> + return &vcinfo->vc[i];
> + }
> +
> + return NULL;
> +}
> +
> +unsigned int mtk_cam_seninf_get_vc_feature(struct v4l2_subdev *sd,
> + unsigned int pad)
This function is useless. Drop it.
> +{
> + struct seninf_vc *pvc = NULL;
> + struct seninf_ctx *ctx = container_of(sd, struct seninf_ctx, subdev);
> +
> + pvc = mtk_cam_seninf_get_vc_by_pad(ctx, pad);
> + if (pvc)
> + return pvc->feature;
> +
> + return VC_NONE;
> +}
> +
[snip]
> +
> +void mtk_cam_seninf_release_mux(struct seninf_ctx *ctx)
> +{
> + struct seninf_mux *ent, *tmp;
> +
> + list_for_each_entry_safe(ent, tmp, &ctx->list_mux, list) {
> + mtk_cam_seninf_mux_put(ctx, ent);
> + }
> +}
> +
> +int mtk_cam_seninf_get_pixelmode(struct v4l2_subdev *sd,
> + int pad_id, int *pixel_mode)
This function is useless. Drop it.
> +{
> + struct seninf_ctx *ctx = container_of(sd, struct seninf_ctx, subdev);
> + struct seninf_vc *vc;
> +
> + vc = mtk_cam_seninf_get_vc_by_pad(ctx, pad_id);
> + if (!vc) {
> + pr_info("%s: invalid pad=%d\n", __func__, pad_id);
> + return -1;
> + }
> +
> + *pixel_mode = vc->pixel_mode;
> +
> + return 0;
> +}
> +
[snip]
> +int mtk_cam_seninf_set_camtg(struct v4l2_subdev *sd, int pad_id, int camtg)
> +{
> + return _mtk_cam_seninf_set_camtg(sd, pad_id, camtg, true);
Squash _mtk_cam_seninf_set_camtg() into mtk_cam_seninf_set_camtg().
> +}
>
[snip]
> +
> +struct seninf_vc {
> + u8 dt;
> + u8 feature;
Because mtk_cam_seninf_get_vc_feature() is useless, so feature is useless.
Drop it.
> + u8 out_pad;
> + u8 pixel_mode;
> + u8 mux; /* allocated per group */
> + u8 cam; /* assigned by cam driver */
> + u8 enable;
> +};
> +
[snip]
> +
> +struct seninf_ctx {
> + struct v4l2_subdev subdev;
> + struct v4l2_async_notifier notifier;
> + struct device *dev;
> + struct v4l2_ctrl_handler ctrl_handler;
> + struct media_pad pads[PAD_MAXCNT];
> + struct v4l2_subdev_format fmt[PAD_MAXCNT];
> + struct seninf_core *core;
> + struct list_head list;
> +
> + u32 port;
> + u32 port_a;
> + u32 port_b;
> + u32 port_num;
> + u32 num_data_lanes;
> + s64 mipi_pixel_rate;
mipi_pixel_rate is never initialized. Drop it.
> + s64 buffered_pixel_rate;
buffered_pixel_rate is used only in update_isp_clk().
update_isp_clk() is useless and drop, so buffered_pixel_rate is useless.
Drop it.
> + s64 customized_pixel_rate;
customized_pixel_rate is useless. Drop it.
> + unsigned int m_csi_efuse;
> +
> + unsigned int is_4d1c:1;
> + unsigned int is_cphy:1;
> + unsigned int is_test_model:4;
is_test_model is useless. Drop it.
> + unsigned int is_secure:1;
> + unsigned int sec_info_addr;
Because mtk_cam_seninf_set_secure() is useless, so is_secure and sec_info_addr are useless.
Drop them.
> + u32 seninf_idx;
> + int pad2cam[PAD_MAXCNT];
> +
> + /* remote sensor */
> + struct v4l2_subdev *sensor_sd;
> + u32 sensor_pad_idx;
> +
> + /* provided by sensor */
> + struct seninf_vcinfo vcinfo;
> + int fps_n;
> + int fps_d;
> +
> + /* dfs */
> + int isp_freq;
isp_freq is useless. Drop it.
> +
> + void __iomem *reg_ana_csi_rx[CSI_PORT_MAX_NUM];
> + void __iomem *reg_ana_dphy_top[CSI_PORT_MAX_NUM];
> + void __iomem *reg_ana_cphy_top[CSI_PORT_MAX_NUM];
> + void __iomem *reg_if_top;
> + void __iomem *reg_if_ctrl[SENINF_NUM];
> + void __iomem *reg_if_cam_mux;
> + void __iomem *reg_if_cam_mux_gcsr;
> + void __iomem *reg_if_cam_mux_pcsr[SENINF_CAM_MUX_NUM];
> + void __iomem *reg_if_tg[SENINF_NUM];
> + void __iomem *reg_if_csi2[SENINF_NUM];
> + void __iomem *reg_if_mux[SENINF_MUX_NUM];
> +
> + /* resources */
> + struct list_head list_mux; /* work mux */
> + struct list_head list_cam_mux;
> +
> + /* flags */
> + unsigned int streaming:1;
> +
> + int cphy_settle_delay_dt;
> + int dphy_settle_delay_dt;
> + int settle_delay_ck;
> + int hs_trail_parameter;
> +
> + int open_refcnt;
> + struct mutex mutex; /* protect seninf context */
> +
> + /* csi irq */
> + unsigned int data_not_enough_cnt;
> + unsigned int err_lane_resync_cnt;
> + unsigned int crc_err_cnt;
> + unsigned int ecc_err_double_cnt;
> + unsigned int ecc_err_corrected_cnt;
> + /* seninf_mux fifo overrun irq */
> + unsigned int fifo_overrun_cnt;
> + /* cam_mux h/v size irq */
> + unsigned int size_err_cnt;
> + /* error flag */
> + unsigned int data_not_enough_flag;
> + unsigned int err_lane_resync_flag;
> + unsigned int crc_err_flag;
> + unsigned int ecc_err_double_flag;
> + unsigned int ecc_err_corrected_flag;
> + unsigned int fifo_overrun_flag;
> + unsigned int size_err_flag;
> +};
> +
[snip]
> +
> +int mtk_cam_seninf_set_cammux_vc(struct seninf_ctx *ctx, int cam_mux,
> + int vc_sel, int dt_sel, int vc_en,
> + int dt_en)
vc_sel is always zero, so just assign 0 in this function and drop vc_sel parameter.
vc_en and dt_en are always !!dt_sel, so it's not necessary to pass vc_en and dt_en as parameter.
Drop these two parameter and use !!dt_sel in this function.
> +{
> + void __iomem *seninf_cam_mux_vc_addr = ctx->reg_if_cam_mux + (cam_mux << 0x2);
> +
> + SENINF_BITS(seninf_cam_mux_vc_addr, SENINF_CAM_MUX0_OPT,
> + RG_SENINF_CAM_MUX0_VC_SEL, vc_sel);
> + SENINF_BITS(seninf_cam_mux_vc_addr, SENINF_CAM_MUX0_OPT,
> + RG_SENINF_CAM_MUX0_DT_SEL, dt_sel);
> + SENINF_BITS(seninf_cam_mux_vc_addr, SENINF_CAM_MUX0_OPT,
> + RG_SENINF_CAM_MUX0_VC_EN, vc_en);
> + SENINF_BITS(seninf_cam_mux_vc_addr, SENINF_CAM_MUX0_OPT,
> + RG_SENINF_CAM_MUX0_DT_EN, dt_en);
> +
> + return 0;
> +}
> +
[snip]
> +int mtk_cam_seninf_set_vc(struct seninf_ctx *ctx, u32 seninf_idx,
> + struct seninf_vcinfo *vcinfo)
> +{
> + void __iomem *seninf_csi2 = ctx->reg_if_csi2[seninf_idx];
> + int i;
> + struct seninf_vc *vc;
> +
> + if (WARN_ON(!vcinfo || !vcinfo->cnt))
> + return -EINVAL;
> +
> + SENINF_WRITE_REG(seninf_csi2, SENINF_CSI2_S0_DI_CTRL, 0);
> + SENINF_WRITE_REG(seninf_csi2, SENINF_CSI2_S1_DI_CTRL, 0);
> + SENINF_WRITE_REG(seninf_csi2, SENINF_CSI2_S2_DI_CTRL, 0);
> + SENINF_WRITE_REG(seninf_csi2, SENINF_CSI2_S3_DI_CTRL, 0);
> + SENINF_WRITE_REG(seninf_csi2, SENINF_CSI2_S4_DI_CTRL, 0);
> + SENINF_WRITE_REG(seninf_csi2, SENINF_CSI2_S5_DI_CTRL, 0);
> + SENINF_WRITE_REG(seninf_csi2, SENINF_CSI2_S6_DI_CTRL, 0);
> + SENINF_WRITE_REG(seninf_csi2, SENINF_CSI2_S7_DI_CTRL, 0);
> +
> + SENINF_WRITE_REG(seninf_csi2, SENINF_CSI2_CH0_CTRL, 0);
> + SENINF_WRITE_REG(seninf_csi2, SENINF_CSI2_CH1_CTRL, 0);
> + SENINF_WRITE_REG(seninf_csi2, SENINF_CSI2_CH2_CTRL, 0);
> + SENINF_WRITE_REG(seninf_csi2, SENINF_CSI2_CH3_CTRL, 0);
> +
> + for (i = 0; i < vcinfo->cnt; i++) {
> + vc = &vcinfo->vc[i];
> +
> + /* General Long Packet Data Types: 0x10-0x17 */
> + if (vc->dt >= 0x10 && vc->dt <= 0x17) {
vc->dt would only be 0, 0x2a, 0x2b, 0x2c, so this checking would always be false.
Drop this.
> + SENINF_BITS(seninf_csi2, SENINF_CSI2_OPT,
> + RG_CSI2_GENERIC_LONG_PACKET_EN, 1);
> + }
> +
> + mtk_cam_seninf_set_di_ch_ctrl(seninf_csi2, i, vc);
> + }
> +
> + dev_dbg(ctx->dev, "DI_CTRL 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
> + readl(seninf_csi2 + SENINF_CSI2_S0_DI_CTRL),
> + readl(seninf_csi2 + SENINF_CSI2_S1_DI_CTRL),
> + readl(seninf_csi2 + SENINF_CSI2_S2_DI_CTRL),
> + readl(seninf_csi2 + SENINF_CSI2_S3_DI_CTRL),
> + readl(seninf_csi2 + SENINF_CSI2_S4_DI_CTRL),
> + readl(seninf_csi2 + SENINF_CSI2_S5_DI_CTRL),
> + readl(seninf_csi2 + SENINF_CSI2_S6_DI_CTRL),
> + readl(seninf_csi2 + SENINF_CSI2_S7_DI_CTRL));
> +
> + dev_dbg(ctx->dev, "CH_CTRL 0x%x 0x%x 0x%x 0x%x\n",
> + readl(seninf_csi2 + SENINF_CSI2_CH0_CTRL),
> + readl(seninf_csi2 + SENINF_CSI2_CH1_CTRL),
> + readl(seninf_csi2 + SENINF_CSI2_CH2_CTRL),
> + readl(seninf_csi2 + SENINF_CSI2_CH3_CTRL));
> +
> + return 0;
> +}
> +
[snip]
> +
> +int mtk_cam_seninf_irq_handler(int irq, void *data)
> +{
> + struct seninf_core *core = (struct seninf_core *)data;
> + unsigned long flags; /* for mipi err detection */
> + struct seninf_ctx *ctx;
> + struct seninf_vc *vc;
> + void __iomem *csi2, *pmux, *seninf_cam_mux;
> + int i;
> + unsigned int csi_irq_ro;
> + unsigned int mux_irq_ro;
> + unsigned int cam_irq_exp_ro;
> + unsigned int cam_irq_res_ro;
> +
> + spin_lock_irqsave(&core->spinlock_irq, flags);
> +
> + /* debug for set_reg case: REG_KEY_CSI_IRQ_EN */
> + if (core->csi_irq_en_flag) {
Because mtk_cam_seninf_set_reg() is useless, so core->csi_irq_en_flag is always zero.
Drop these code.
> + list_for_each_entry(ctx, &core->list, list) {
> + csi2 = ctx->reg_if_csi2[ctx->seninf_idx];
> + csi_irq_ro =
> + readl(csi2 + SENINF_CSI2_IRQ_STATUS);
> +
> + if (csi_irq_ro) {
> + SENINF_WRITE_REG(csi2, SENINF_CSI2_IRQ_STATUS,
> + 0xFFFFFFFF);
> + }
> +
> + if (csi_irq_ro & RO_CSI2_ECC_ERR_CORRECTED_IRQ)
> + ctx->ecc_err_corrected_cnt++;
> + if (csi_irq_ro & RO_CSI2_ECC_ERR_DOUBLE_IRQ)
> + ctx->ecc_err_double_cnt++;
> + if (csi_irq_ro & RO_CSI2_CRC_ERR_IRQ)
> + ctx->crc_err_cnt++;
> + if (csi_irq_ro & RO_CSI2_ERR_LANE_RESYNC_IRQ)
> + ctx->err_lane_resync_cnt++;
> + if (csi_irq_ro & RO_CSI2_RECEIVE_DATA_NOT_ENOUGH_IRQ)
> + ctx->data_not_enough_cnt++;
> +
> + for (i = 0; i < ctx->vcinfo.cnt; i++) {
> + vc = &ctx->vcinfo.vc[i];
> + pmux = ctx->reg_if_mux[vc->mux];
> + seninf_cam_mux = ctx->reg_if_cam_mux;
> +
> + mux_irq_ro = readl(pmux +
> + SENINF_MUX_IRQ_STATUS);
> +
> + cam_irq_exp_ro = readl(seninf_cam_mux +
> + SENINF_CAM_MUX0_CHK_CTL_1 +
> + (0x10 * (vc->cam)));
> +
> + cam_irq_res_ro = readl(seninf_cam_mux +
> + SENINF_CAM_MUX0_CHK_RES +
> + (0x10 * (vc->cam)));
> +
> + if (mux_irq_ro)
> + SENINF_WRITE_REG(pmux,
> + SENINF_MUX_IRQ_STATUS,
> + 0xFFFFFFFF);
> +
> + if (cam_irq_res_ro != cam_irq_exp_ro)
> + SENINF_WRITE_REG(seninf_cam_mux,
> + SENINF_CAM_MUX0_CHK_RES +
> + (0x10 * (vc->cam)),
> + 0xFFFFFFFF);
> +
> + if (mux_irq_ro & (0x1 << 0))
> + ctx->fifo_overrun_cnt++;
> +
> + if (cam_irq_res_ro != cam_irq_exp_ro)
> + ctx->size_err_cnt++;
> + }
> +
> + /* dump status counter: debug for electrical signal */
> + if (ctx->data_not_enough_cnt >= core->detection_cnt ||
> + ctx->err_lane_resync_cnt >= core->detection_cnt ||
> + ctx->crc_err_cnt >= core->detection_cnt ||
> + ctx->ecc_err_double_cnt >= core->detection_cnt ||
> + ctx->ecc_err_corrected_cnt >= core->detection_cnt ||
> + ctx->fifo_overrun_cnt >= core->detection_cnt ||
> + ctx->size_err_cnt >= core->detection_cnt) {
> + /* disable all interrupts */
> + SENINF_WRITE_REG(csi2, SENINF_CSI2_IRQ_EN, 0x80000000);
> +
> + if (ctx->data_not_enough_cnt >= core->detection_cnt)
> + ctx->data_not_enough_flag = 1;
> + if (ctx->err_lane_resync_cnt >= core->detection_cnt)
> + ctx->err_lane_resync_flag = 1;
> + if (ctx->crc_err_cnt >= core->detection_cnt)
> + ctx->crc_err_flag = 1;
> + if (ctx->ecc_err_double_cnt >= core->detection_cnt)
> + ctx->ecc_err_double_flag = 1;
> + if (ctx->ecc_err_corrected_cnt >= core->detection_cnt)
> + ctx->ecc_err_corrected_flag = 1;
> + if (ctx->fifo_overrun_cnt >= core->detection_cnt)
> + ctx->fifo_overrun_flag = 1;
> + if (ctx->size_err_cnt >= core->detection_cnt)
> + ctx->size_err_flag = 1;
> + }
> + }
> + }
> +
> + spin_unlock_irqrestore(&core->spinlock_irq, flags);
> +
> + return 0;
> +}
> +
> +int mtk_cam_seninf_set_sw_cfg_busy(struct seninf_ctx *ctx, bool enable, int index)
This function is useless, drop it.
> +{
> + void __iomem *seninf_cam_mux = ctx->reg_if_cam_mux;
> + unsigned int mask;
> +
> + mask = index ? RG_SENINF_CAM_MUX_DYN_SWITCH_BSY1 : RG_SENINF_CAM_MUX_DYN_SWITCH_BSY0;
> +
> + SENINF_BITS_VAR(seninf_cam_mux, SENINF_CAM_MUX_DYN_CTRL, mask, enable);
> +
> + return 0;
> +}
> +
> +int mtk_cam_seninf_reset_cam_mux_dyn_en(struct seninf_ctx *ctx, int index)
This function is useless, drop it.
> +{
> + void __iomem *seninf_cam_mux = ctx->reg_if_cam_mux;
> +
> + if (index == 0)
> + SENINF_BITS(seninf_cam_mux, SENINF_CAM_MUX_DYN_EN,
> + RG_SENINF_CAM_MUX_DYN_SWITCH_EN0, 0);
> + else
> + SENINF_BITS(seninf_cam_mux, SENINF_CAM_MUX_DYN_EN,
> + RG_SENINF_CAM_MUX_DYN_SWITCH_EN1, 0);
> + return 0;
> +}
> +
> +int mtk_cam_seninf_enable_global_drop_irq(struct seninf_ctx *ctx, bool enable,
> + int index)
This function is useless, drop it.
> +{
> + void __iomem *seninf_cam_mux = ctx->reg_if_cam_mux;
> +
> + if (index == 0)
> + SENINF_BITS(seninf_cam_mux, SENINF_CAM_MUX_IRQ_EN,
> + RG_SENINF_CAM_MUX15_HSIZE_ERR_IRQ_EN, enable);
> + else
> + SENINF_BITS(seninf_cam_mux, SENINF_CAM_MUX_IRQ_EN,
> + RG_SENINF_CAM_MUX15_VSIZE_ERR_IRQ_EN, enable);
> + return 0;
> +}
> +
> +int mtk_cam_seninf_enable_cam_mux_vsync_irq(struct seninf_ctx *ctx, bool enable,
> + int cam_mux)
This function is useless, drop it.
> +{
> + void __iomem *seninf_cam_mux = ctx->reg_if_cam_mux;
> + int tmp = 0;
> +
> + tmp = SENINF_READ_BITS(seninf_cam_mux, SENINF_CAM_MUX_VSYNC_IRQ_EN,
> + RG_SENINF_CAM_MUX_VSYNC_IRQ_EN);
> + if (enable)
> + tmp |= (enable << cam_mux);
> + else
> + tmp &= ~(enable << cam_mux);
> + SENINF_BITS(seninf_cam_mux, SENINF_CAM_MUX_VSYNC_IRQ_EN,
> + RG_SENINF_CAM_MUX_VSYNC_IRQ_EN, tmp);
> + return 0;
> +}
> +
> +int mtk_cam_seninf_disable_all_cam_mux_vsync_irq(struct seninf_ctx *ctx)
This function is useless, drop it.
> +{
> + void __iomem *seninf_cam_mux = ctx->reg_if_cam_mux;
> +
> + SENINF_BITS(seninf_cam_mux, SENINF_CAM_MUX_VSYNC_IRQ_EN,
> + RG_SENINF_CAM_MUX_VSYNC_IRQ_EN, 0);
> + return 0;
> +}
> +
> +int mtk_cam_seninf_set_reg(struct seninf_ctx *ctx, u32 key, u32 val)
This function is useless, drop it.
Regards,
CK
> +{
> + int i;
> + void __iomem *base = ctx->reg_ana_dphy_top[ctx->port];
> + void __iomem *csi2 = ctx->reg_if_csi2[ctx->seninf_idx];
> + void __iomem *pmux, *pcammux;
> + struct seninf_vc *vc;
> + struct seninf_core *core;
> + struct seninf_ctx *ctx_;
> + void __iomem *csi2_;
> +
> + core = dev_get_drvdata(ctx->dev->parent);
> +
> + if (!ctx->streaming)
> + return 0;
> +
> + dev_dbg(ctx->dev, "%s key = 0x%x, val = 0x%x\n", __func__, key, val);
> +
> + switch (key) {
> + case REG_KEY_SETTLE_CK:
> + SENINF_BITS(base, DPHY_RX_CLOCK_LANE0_HS_PARAMETER,
> + RG_DPHY_RX_LC0_HS_SETTLE_PARAMETER, val);
> + SENINF_BITS(base, DPHY_RX_CLOCK_LANE1_HS_PARAMETER,
> + RG_DPHY_RX_LC1_HS_SETTLE_PARAMETER, val);
> + break;
> + case REG_KEY_SETTLE_DT:
> + SENINF_BITS(base, DPHY_RX_DATA_LANE0_HS_PARAMETER,
> + RG_CDPHY_RX_LD0_TRIO0_HS_SETTLE_PARAMETER, val);
> + SENINF_BITS(base, DPHY_RX_DATA_LANE1_HS_PARAMETER,
> + RG_CDPHY_RX_LD1_TRIO1_HS_SETTLE_PARAMETER, val);
> + SENINF_BITS(base, DPHY_RX_DATA_LANE2_HS_PARAMETER,
> + RG_CDPHY_RX_LD2_TRIO2_HS_SETTLE_PARAMETER, val);
> + SENINF_BITS(base, DPHY_RX_DATA_LANE3_HS_PARAMETER,
> + RG_CDPHY_RX_LD3_TRIO3_HS_SETTLE_PARAMETER, val);
> + break;
> + case REG_KEY_HS_TRAIL_EN:
> + SENINF_BITS(base, DPHY_RX_DATA_LANE0_HS_PARAMETER,
> + RG_DPHY_RX_LD0_HS_TRAIL_EN, val);
> + SENINF_BITS(base, DPHY_RX_DATA_LANE1_HS_PARAMETER,
> + RG_DPHY_RX_LD1_HS_TRAIL_EN, val);
> + SENINF_BITS(base, DPHY_RX_DATA_LANE2_HS_PARAMETER,
> + RG_DPHY_RX_LD2_HS_TRAIL_EN, val);
> + SENINF_BITS(base, DPHY_RX_DATA_LANE3_HS_PARAMETER,
> + RG_DPHY_RX_LD3_HS_TRAIL_EN, val);
> + break;
> + case REG_KEY_HS_TRAIL_PARAM:
> + SENINF_BITS(base, DPHY_RX_DATA_LANE0_HS_PARAMETER,
> + RG_DPHY_RX_LD0_HS_TRAIL_PARAMETER, val);
> + SENINF_BITS(base, DPHY_RX_DATA_LANE1_HS_PARAMETER,
> + RG_DPHY_RX_LD1_HS_TRAIL_PARAMETER, val);
> + SENINF_BITS(base, DPHY_RX_DATA_LANE2_HS_PARAMETER,
> + RG_DPHY_RX_LD2_HS_TRAIL_PARAMETER, val);
> + SENINF_BITS(base, DPHY_RX_DATA_LANE3_HS_PARAMETER,
> + RG_DPHY_RX_LD3_HS_TRAIL_PARAMETER, val);
> + break;
> + case REG_KEY_CSI_IRQ_STAT:
> + SENINF_WRITE_REG(csi2, SENINF_CSI2_IRQ_STATUS,
> + val & 0xFFFFFFFF);
> + break;
> + case REG_KEY_MUX_IRQ_STAT:
> + for (i = 0; i < ctx->vcinfo.cnt; i++) {
> + vc = &ctx->vcinfo.vc[i];
> + pmux = ctx->reg_if_mux[vc->mux];
> + SENINF_WRITE_REG(pmux, SENINF_MUX_IRQ_STATUS,
> + val & 0xFFFFFFFF);
> + }
> + break;
> + case REG_KEY_CAMMUX_IRQ_STAT:
> + for (i = 0; i < ctx->vcinfo.cnt; i++) {
> + vc = &ctx->vcinfo.vc[i];
> + pcammux = ctx->reg_if_cam_mux;
> + SENINF_WRITE_REG(pcammux, SENINF_CAM_MUX_IRQ_STATUS,
> + val & 0xFFFFFFFF);
> + }
> + break;
> + case REG_KEY_CSI_IRQ_EN:
> + {
> + if (!val) {
> + core->csi_irq_en_flag = 0;
> + return 0;
> + }
> +
> + core->csi_irq_en_flag = 1;
> + core->detection_cnt = val;
> + list_for_each_entry(ctx_, &core->list, list) {
> + csi2_ = ctx_->reg_if_csi2[ctx_->seninf_idx];
> + SENINF_WRITE_REG(csi2_, SENINF_CSI2_IRQ_EN,
> + 0xA0002058);
> + }
> + }
> + break;
> + }
> +
> + return 0;
> +}
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20250716/f7e131b4/attachment-0001.htm>
More information about the dri-devel
mailing list