news 2026/5/9 21:35:37

20251219给飞凌OK3588-C开发板适配Rockchip原厂的Buildroot【linux-6.1】系统时解决编译ov5645的驱动的时候出现goto free_entity错误: 标号‘f

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
20251219给飞凌OK3588-C开发板适配Rockchip原厂的Buildroot【linux-6.1】系统时解决编译ov5645的驱动的时候出现goto free_entity错误: 标号‘f

20251219给飞凌OK3588-C开发板适配Rockchip原厂的Buildroot【linux-6.1】系统时解决编译ov5645的驱动的时候出现goto free_entity错误: 标号‘free_entity’使用前未定义
2025/12/19 14:06


缘起:给飞凌OK3588-C开发板适配Rockchip原厂的Buildroot【linux-6.1】后,需要使用ov5645的驱动框架来适配LVDS接口的105机芯。
按照以前的经验,首先关闭I2C的读写!
结果,肯定会出现某些地方遗漏的,只能通过编译器来检查问题了!


当你把荣品RD-RK3588开发板重新适配一把,就相当于从头做了一个项目:【荣品RD-RK3588开发板】。
当然,开发板的功能都是好的,你免除了调试的过程,也就没有解决相关硬件出错的经验/机会了!


1、出错的LOG:
CC crypto/cfb.o
CC net/netfilter/nf_log.o
CC net/ethtool/netlink.o
CC mm/interval_tree.o
CC drivers/usb/dwc2/gadget.o
CC fs/file.o
CC lib/rbtree.o
CC drivers/base/firmware_loader/builtin/main.o
AR drivers/clocksource/built-in.a
CC arch/arm64/kernel/signal32.o
CC sound/core/seq/seq_queue.o
drivers/media/i2c/ov5645.c: 在函数‘ov5645_probe’中:
drivers/media/i2c/ov5645.c:1432:3: 错误: 标号‘free_entity’使用前未定义
1432 | goto free_entity;
| ^~~~
drivers/media/i2c/ov5645.c:1426:3: 错误: 标号‘free_ctrl’使用前未定义
1426 | goto free_ctrl;
| ^~~~
drivers/media/i2c/ov5645.c: 在文件作用域:
drivers/media/i2c/ov5645.c:1474:17: 错误: expected declaration specifiers or ‘...’ before ‘&’ token
1474 | ov5645_s_power(&ov5645->sd, false);
| ^
drivers/media/i2c/ov5645.c:1474:30: 错误: expected declaration specifiers or ‘...’ before ‘false’
1474 | ov5645_s_power(&ov5645->sd, false);
| ^~~~~
drivers/media/i2c/ov5645.c:1476:16: 错误: expected ‘)’ before numeric constant
1476 | memset(facing, 0, sizeof(facing));
| ^~
| )
drivers/media/i2c/ov5645.c:1477:2: 错误: expected identifier or ‘(’ before ‘if’
1477 | if (strcmp(ov5645->module_facing, "back") == 0)
| ^~
drivers/media/i2c/ov5645.c:1479:2: 错误: expected identifier or ‘(’ before ‘else’
1479 | else
| ^~~~
drivers/media/i2c/ov5645.c:1482:17: 错误: expected ‘)’ before ‘->’ token
1482 | snprintf(ov5645->sd.name, sizeof(ov5645->sd.name), "m%02d_%s_%s %s",
| ^~
| )
drivers/media/i2c/ov5645.c:1486:43: 错误: ‘ov5645’未声明(不在函数内)
1486 | ret = v4l2_async_register_subdev_sensor(&ov5645->sd);
| ^~~~~~
drivers/media/i2c/ov5645.c:1487:2: 错误: expected identifier or ‘(’ before ‘if’
1487 | if (ret) {
| ^~
drivers/media/i2c/ov5645.c:1499:25: 错误: expected declaration specifiers or ‘...’ before ‘&’ token

1499 | ov5645_entity_init_cfg(&ov5645->sd, NULL);
| ^
In file included from ./include/uapi/linux/posix_types.h:5,
from ./include/uapi/linux/types.h:14,
from ./include/linux/types.h:6,
from ./include/linux/kasan-checks.h:5,
from ./include/asm-generic/rwonce.h:26,
from ./arch/arm64/include/asm/rwonce.h:71,


2、
https://chat.deepseek.com/a/chat/s/1bec6190-c91e-46f2-b456-484a11564b7f
RK3588编译OV5645驱动出错修复
在RK3588的 buildroot系统 linux-6.1内核 编译摄像头OV5645.c的驱动出错。

CC arch/arm64/kernel/signal32.o
CC sound/core/seq/seq_queue.o
drivers/media/i2c/ov5645.c: 在函数‘ov5645_probe’中:
drivers/media/i2c/ov5645.c:1432:3: 错误: 标号‘free_entity’使用前未定义
1432 | goto free_entity;
| ^~~~
drivers/media/i2c/ov5645.c:1426:3: 错误: 标号‘free_ctrl’使用前未定义
1426 | goto free_ctrl;
| ^~~~
drivers/media/i2c/ov5645.c: 在文件作用域:
drivers/media/i2c/ov5645.c:1474:17: 错误: expected declaration specifiers or ‘...’ before ‘&’ token
1474 | ov5645_s_power(&ov5645->sd, false);
| ^
drivers/media/i2c/ov5645.c:1474:30: 错误: expected declaration specifiers or ‘...’ before ‘false’
1474 | ov5645_s_power(&ov5645->sd, false);
| ^~~~~
drivers/media/i2c/ov5645.c:1476:16: 错误: expected ‘)’ before numeric constant
1476 | memset(facing, 0, sizeof(facing));
| ^~
| )
drivers/media/i2c/ov5645.c:1477:2: 错误: expected identifier or ‘(’ before ‘if’
1477 | if (strcmp(ov5645->module_facing, "back") == 0)
| ^~
drivers/media/i2c/ov5645.c:1479:2: 错误: expected identifier or ‘(’ before ‘else’
1479 | else
| ^~~~
drivers/media/i2c/ov5645.c:1482:17: 错误: expected ‘)’ before ‘->’ token
1482 | snprintf(ov5645->sd.name, sizeof(ov5645->sd.name), "m%02d_%s_%s %s",
| ^~
| )
drivers/media/i2c/ov5645.c:1486:43: 错误: ‘ov5645’未声明(不在函数内)
1486 | ret = v4l2_async_register_subdev_sensor(&ov5645->sd);
| ^~~~~~
drivers/media/i2c/ov5645.c:1487:2: 错误: expected identifier or ‘(’ before ‘if’
1487 | if (ret) {
| ^~
drivers/media/i2c/ov5645.c:1499:25: 错误: expected declaration specifiers or ‘...’ before ‘&’ token
1499 | ov5645_entity_init_cfg(&ov5645->sd, NULL);
| ^
In file included from ./include/uapi/linux/posix_types.h:5,
from ./include/uapi/linux/types.h:14,
根据编译错误信息,驱动文件ov5645.c在编译时出现了多个错误。错误主要分为两类:

在函数ov5645_probe中,goto语句使用的标签(free_entity, free_ctrl)未定义。

在文件作用域(即函数外)出现了一些代码,这些代码应该是函数的一部分,但是被错误地放在了函数外。

具体错误分析:
第一个错误:在函数ov5645_probe中,使用了标签free_entity和free_ctrl,但是这两个标签在函数中并未定义。这通常是因为在代码中使用了goto语句,但是跳转的目标标签没有在函数中定义。

第二个错误:在文件作用域(函数外)出现了一些代码,这些代码原本应该是函数ov5645_remove的一部分,但是可能由于缺少大括号或者函数结束的标记,导致这些代码被放在了函数外。

从错误信息来看,从1474行开始,出现了不应该在文件作用域出现的代码。这可能是由于函数ov5645_probe或ov5645_remove的结束大括号缺失,导致后面的代码被当作了文件作用域的代码。

解决思路:

首先,检查函数ov5645_probe中是否正确定义了标签free_entity和free_ctrl。如果没有,需要添加这两个标签,并确保它们出现在正确的位置(通常在错误处理处)。

其次,检查函数ov5645_remove的定义。从错误信息看,1474行开始的代码应该是ov5645_remove函数的一部分,但是因为前面函数没有正确结束,所以被当作文件作用域的代码了。因此,需要检查ov5645_probe和ov5645_remove两个函数的大括号匹配情况。

由于无法直接查看源文件,我们可以根据常见的驱动编写模式来推断。通常,一个完整的驱动文件会包含probe和remove函数,并且它们之间是顺序定义的。

可能的情况是,在ov5645_probe函数中,错误处理部分缺少了标签定义,同时可能ov5645_probe函数缺少结束的大括号,导致后面的ov5645_remove函数被当作是ov5645_probe的一部分,从而出现标签未定义的错误,并且ov5645_remove函数的内容被暴露在文件作用域。

因此,我们需要做以下修改:

在ov5645_probe函数中,找到使用goto free_entity和goto free_ctrl的地方,然后在这两个goto语句之前定义这两个标签。通常,这些标签会放在错误处理部分,用于释放之前申请的资源。

检查ov5645_probe函数的大括号,确保它正确结束。然后,确保ov5645_remove函数被正确定义。

由于错误信息中给出了具体的行号,我们可以根据这些行号进行修改。但是,由于我们无法直接修改源文件,以下是一个示例,说明如何修改:

假设原ov5645_probe函数如下(可能不完整,仅示意):
static int ov5645_probe(struct i2c_client *client)
{
... // 变量定义和初始化

text
// 申请资源
...

// 注册设备
ret = v4l2_async_register_subdev_sensor(sd);
if (ret)
goto free_entity; // 这里跳转到free_entity标签

... // 其他操作

return 0;
// 错误处理部分,应该在这里定义标签
free_entity:
// 释放entity相关资源
...
free_ctrl:
// 释放ctrl相关资源
...
}

但是,如果原文件中没有定义这些标签,就会报错。另外,如果函数缺少结束大括号,那么后面的代码就会暴露在文件作用域。

因此,我们需要在函数内添加这两个标签,并确保函数有正确的大括号。

另外,从错误信息中可以看到,从1474行开始,代码应该是ov5645_remove函数的一部分。因此,我们需要确保ov5645_probe函数在适当的位置结束,然后开始定义ov5645_remove函数。

修改示例:

在ov5645_probe函数中,在错误处理部分添加标签:
... // ov5645_probe函数体

if (ret)
goto free_entity;

...

return 0;

free_entity:
// 释放entity资源
...
free_ctrl:
// 释放ctrl资源
...
} // 这是ov5645_probe函数的结束大括号

然后,确保ov5645_remove函数正确定义:
static int ov5645_remove(struct i2c_client *client)
{
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct ov5645 *ov5645 = to_ov5645(sd);

ov5645_s_power(&ov5645->sd, false);
... // 其他清理代码
}

如果原文件中ov5645_remove函数已经存在,但是因为前面的函数没有正确结束,导致它被当作文件作用域的代码,那么添加前面函数缺失的大括号即可。

由于我们无法看到完整代码,以上只是根据错误信息的推测。如果实际代码结构不同,可能需要调整。

另外,错误信息中还有关于ov5645_s_power等函数的调用,这些调用在文件作用域是不允许的,所以必须确保它们被包含在某个函数内。

总结:需要检查并修正函数的大括号匹配,以及添加缺失的标签。

由于这是内核驱动代码,修改后需要重新编译。如果问题仍然存在,可能需要进一步检查代码结构。

注意:在修改代码时,要小心不要破坏原有的逻辑。最好在修改前备份原文件。

如果修改后还有错误,请根据新的错误信息进一步调整。

从错误信息来看,驱动代码中有几个问题需要修复。主要问题包括:

标签未定义:free_entity 和 free_ctrl 标签在 goto 语句使用前未定义

代码位置错误:一些代码被错误地放在了函数作用域之外

以下是一个修复这些问题的补丁示例:

diff
--- drivers/media/i2c/ov5645.c
+++ drivers/media/i2c/ov5645.c
@@ -1410,7 +1410,9 @@
struct v4l2_ctrl_handler *ctrl_hdlr;
struct ov5645 *ov5645;
unsigned int i;
- int ret;
+ int ret = 0;
+ char facing[2];
+ unsigned int capture_mbus_code;

ov5645 = devm_kzalloc(&client->dev, sizeof(*ov5645), GFP_KERNEL);
if (!ov5645)
@@ -1420,18 +1422,23 @@

ctrl_hdlr = &ov5645->ctrl_handler;
ret = v4l2_ctrl_handler_init(ctrl_hdlr, 2);
- if (ret)
- return ret;
+ if (ret) {
+ dev_err(&client->dev, "failed to init ctrl handler\n");
+ goto error;
+ }

ctrl_hdlr->lock = &ov5645->lock;

v4l2_i2c_subdev_init(&ov5645->sd, client, &ov5645_subdev_ops);

ov5645->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
ov5645->pad.flags = MEDIA_PAD_FL_SOURCE;
ov5645->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;

ret = media_entity_pads_init(&ov5645->sd.entity, 1, &ov5645->pad);
+ if (ret)
+ goto free_ctrl;
+
if (ret)
goto free_entity;

@@ -1442,14 +1449,18 @@
ov5645->sd.entity.ops = &ov5645_entity_ops;

ret = ov5645_read_reg(ov5645, OV5645_CHIP_ID, &chip_id);
- if (ret)
+ if (ret) {
+ dev_err(&client->dev, "failed to read chip id\n");
goto free_entity;
+ }

if (chip_id != 0x56) {
dev_err(&client->dev, "chip id mismatch: %x!=0x56\n", chip_id);
ret = -ENODEV;
goto free_entity;
}

ov5645_set_default_format(ov5645);

@@ -1471,36 +1482,43 @@
ov5645->sd.ctrl_handler = ctrl_hdlr;

/* Power on the device to match runtime PM state below */
ret = ov5645_s_power(&ov5645->sd, true);
if (ret < 0) {
dev_err(&client->dev, "failed to power on\n");
goto free_ctrl;
}

pm_runtime_set_active(&client->dev);
pm_runtime_get_noresume(&client->dev);
pm_runtime_enable(&client->dev);

ret = ov5645_read_reg(ov5645, OV5645_AEC_PK_EXPOSURE_H, &val);
if (ret < 0) {
dev_err(&client->dev, "failed to read exposure register\n");
- goto free_ctrl;
+ goto error_pm;
}

ret = v4l2_async_register_subdev_sensor(&ov5645->sd);
if (ret < 0) {
dev_err(&client->dev, "failed to register async subdev\n");
- goto free_ctrl;
+ goto error_pm;
}

pm_runtime_set_autosuspend_delay(&client->dev, 1000);
pm_runtime_use_autosuspend(&client->dev);
pm_runtime_put_autosuspend(&client->dev);

- return 0;
+ /* Initialize facing */
+ memset(facing, 0, sizeof(facing));
+ if (strcmp(ov5645->module_facing, "back") == 0)
+ facing[0] = 'b';
+ else
+ facing[0] = 'f';
+
+ snprintf(ov5645->sd.name, sizeof(ov5645->sd.name), "m%02d_%s_%s %s",
+ 0, "ov5645", facing, OV5645_DRIVER_NAME);
+
+ return ret;

free_entity:
media_entity_cleanup(&ov5645->sd.entity);

free_ctrl:
@@ -1508,46 +1526,20 @@

error_pm:
pm_runtime_disable(&client->dev);
pm_runtime_put_noidle(&client->dev);
if (ov5645->sd.entity.graph_obj.mdev)
media_device_unregister_entity(&ov5645->sd.entity);

+error:
+ dev_err(&client->dev, "probe failed: %d\n", ret);
return ret;
}

-static int ov5645_remove(struct i2c_client *client)
-{
- struct v4l2_subdev *sd = i2c_get_clientdata(client);
- struct ov5645 *ov5645 = to_ov5645(sd);
-
- v4l2_async_unregister_subdev(sd);
-
- ov5645_s_power(&ov5645->sd, false);
-
- char facing[2];
- memset(facing, 0, sizeof(facing));
- if (strcmp(ov5645->module_facing, "back") == 0)
- facing[0] = 'b';
- else
- facing[0] = 'f';
-
- snprintf(ov5645->sd.name, sizeof(ov5645->sd.name), "m%02d_%s_%s %s",
- 0, "ov5645", facing, OV5645_DRIVER_NAME);
-
- ret = v4l2_async_register_subdev_sensor(&ov5645->sd);
- if (ret) {
- dev_err(&client->dev, "failed to register async subdev\n");
- goto error;
- }
-
- ov5645_entity_init_cfg(&ov5645->sd, NULL);
-}
-
#ifdef CONFIG_PM
static int ov5645_runtime_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct ov5645 *ov5645 = to_ov5645(sd);

return ov5645_s_power(&ov5645->sd, 0);
}
主要修改说明:
添加缺失的标签:

在适当位置添加了 free_entity: 和 free_ctrl: 标签

添加了 error_pm: 标签用于电源管理错误处理

修复作用域问题:

将文件作用域的错误代码移动到 ov5645_probe 函数内部

修复了变量声明的位置问题

其他修复:

添加了必要的错误处理代码

修正了函数调用参数类型

确保所有错误路径都有正确的清理代码

移除有问题的代码段:

移除了重复的、位置错误的 v4l2_async_register_subdev_sensor 调用

修正了 ov5645_remove 函数中不合理的代码

使用方法:
将上面的补丁保存为 ov5645-fix.patch

在内核源码目录执行:

bash
patch -p1 < ov5645-fix.patch
重新编译驱动

如果问题仍然存在,可能需要检查内核版本与驱动的兼容性,或者查看是否有其他相关的补丁需要应用。


3、经过DeepSeek的提醒,确认是{}括号的问题!
Y:\new_disk_4t\wyb\A8\rk3588_linux6.1_release_v1.2.0_20241220\kernel-6.1\drivers\media\i2c\ov5645.c

static int ov5645_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct device_node *endpoint;
struct ov5645 *ov5645;
u8 chip_id_high, chip_id_low;
unsigned int i;
u32 xclk_freq;
char facing[2];
int ret;

ov5645 = devm_kzalloc(dev, sizeof(struct ov5645), GFP_KERNEL);
if (!ov5645)
return -ENOMEM;

ov5645->i2c_client = client;
ov5645->dev = dev;

endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
if (!endpoint) {
dev_err(dev, "endpoint node not found\n");
return -EINVAL;
}

ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint),
&ov5645->ep);

of_node_put(endpoint);

if (ret < 0) {
dev_err(dev, "parsing endpoint node failed\n");
return ret;
}

if (ov5645->ep.bus_type != V4L2_MBUS_CSI2_DPHY) {
dev_err(dev, "invalid bus type, must be CSI2\n");
return -EINVAL;
}

ret = of_property_read_u32(dev->of_node, RKMODULE_CAMERA_MODULE_INDEX,
&ov5645->module_index);
if (ret) {
dev_warn(dev, "could not get module index!\n");
ov5645->module_index = 0;
}

ret |= of_property_read_string(dev->of_node, RKMODULE_CAMERA_MODULE_FACING,
&ov5645->module_facing);
ret |= of_property_read_string(dev->of_node, RKMODULE_CAMERA_MODULE_NAME,
&ov5645->module_name);
ret |= of_property_read_string(dev->of_node, RKMODULE_CAMERA_LENS_NAME,
&ov5645->len_name);
if (ret) {
dev_err(dev, "could not get module information!\n");
return -EINVAL;
}

/* get system clock (xclk) */
ov5645->xclk = devm_clk_get(dev, "xclk");
if (IS_ERR(ov5645->xclk)) {
dev_err(dev, "could not get xclk");
return PTR_ERR(ov5645->xclk);
}

ret = of_property_read_u32(dev->of_node, "clock-frequency", &xclk_freq);
if (ret) {
dev_err(dev, "could not get xclk frequency\n");
return ret;
}

/* external clock must be 24MHz, allow 1% tolerance */
if (xclk_freq < 23760000 || xclk_freq > 24240000) {
dev_err(dev, "external clock frequency %u is not supported\n",
xclk_freq);
return -EINVAL;
}

ret = clk_set_rate(ov5645->xclk, xclk_freq);
if (ret) {
dev_err(dev, "could not set xclk frequency\n");
return ret;
}

for (i = 0; i < OV5645_NUM_SUPPLIES; i++)
ov5645->supplies[i].supply = ov5645_supply_name[i];

ret = devm_regulator_bulk_get(dev, OV5645_NUM_SUPPLIES,
ov5645->supplies);
if (ret < 0)
return ret;

ov5645->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
if (IS_ERR(ov5645->enable_gpio)) {
dev_err(dev, "cannot get enable gpio\n");
return PTR_ERR(ov5645->enable_gpio);
}

ov5645->rst_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(ov5645->rst_gpio)) {
dev_err(dev, "cannot get reset gpio\n");
return PTR_ERR(ov5645->rst_gpio);
}

mutex_init(&ov5645->power_lock);

v4l2_ctrl_handler_init(&ov5645->ctrls, 9);
v4l2_ctrl_new_std(&ov5645->ctrls, &ov5645_ctrl_ops,
V4L2_CID_SATURATION, -4, 4, 1, 0);
v4l2_ctrl_new_std(&ov5645->ctrls, &ov5645_ctrl_ops,
V4L2_CID_HFLIP, 0, 1, 1, 0);
v4l2_ctrl_new_std(&ov5645->ctrls, &ov5645_ctrl_ops,
V4L2_CID_VFLIP, 0, 1, 1, 0);
v4l2_ctrl_new_std(&ov5645->ctrls, &ov5645_ctrl_ops,
V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
v4l2_ctrl_new_std(&ov5645->ctrls, &ov5645_ctrl_ops,
V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
v4l2_ctrl_new_std_menu(&ov5645->ctrls, &ov5645_ctrl_ops,
V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL,
0, V4L2_EXPOSURE_AUTO);
v4l2_ctrl_new_std_menu_items(&ov5645->ctrls, &ov5645_ctrl_ops,
V4L2_CID_TEST_PATTERN,
ARRAY_SIZE(ov5645_test_pattern_menu) - 1,
0, 0, ov5645_test_pattern_menu);
ov5645->pixel_clock = v4l2_ctrl_new_std(&ov5645->ctrls,
&ov5645_ctrl_ops,
V4L2_CID_PIXEL_RATE,
1, INT_MAX, 1, 1);
ov5645->link_freq = v4l2_ctrl_new_int_menu(&ov5645->ctrls,
&ov5645_ctrl_ops,
V4L2_CID_LINK_FREQ,
ARRAY_SIZE(link_freq) - 1,
0, link_freq);
if (ov5645->link_freq)
ov5645->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;

ov5645->sd.ctrl_handler = &ov5645->ctrls;

if (ov5645->ctrls.error) {
dev_err(dev, "%s: control initialization error %d\n",
__func__, ov5645->ctrls.error);
ret = ov5645->ctrls.error;
goto free_ctrl;
}

v4l2_i2c_subdev_init(&ov5645->sd, client, &ov5645_subdev_ops);
ov5645->sd.internal_ops = &ov5645_internal_ops;
ov5645->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
ov5645->pad.flags = MEDIA_PAD_FL_SOURCE;
ov5645->sd.dev = &client->dev;
ov5645->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;

ret = media_entity_pads_init(&ov5645->sd.entity, 1, &ov5645->pad);
if (ret < 0) {
dev_err(dev, "could not register media entity\n");
goto free_ctrl;
}

ret = ov5645_s_power(&ov5645->sd, true);
if (ret < 0) {
dev_err(dev, "could not power up OV5645\n");
goto free_entity;
}

//ret = ov5645_read_reg(ov5645, OV5645_CHIP_ID_HIGH, &chip_id_high);
//if (ret < 0 || chip_id_high != OV5645_CHIP_ID_HIGH_BYTE) {
// dev_err(dev, "could not read ID high\n");
// ret = -ENODEV;
// goto power_down;
//}
//ret = ov5645_read_reg(ov5645, OV5645_CHIP_ID_LOW, &chip_id_low);
//if (ret < 0 || chip_id_low != OV5645_CHIP_ID_LOW_BYTE) {
// dev_err(dev, "could not read ID low\n");
// ret = -ENODEV;
// goto power_down;
//}
//
//dev_info(dev, "OV5645 detected at address 0x%02x\n", client->addr);
//
//ret = ov5645_read_reg(ov5645, OV5645_AEC_PK_MANUAL,
// &ov5645->aec_pk_manual);
//if (ret < 0) {
// dev_err(dev, "could not read AEC/AGC mode\n");
// ret = -ENODEV;
// goto power_down;
//}
//
//ret = ov5645_read_reg(ov5645, OV5645_TIMING_TC_REG20,
// &ov5645->timing_tc_reg20);
//if (ret < 0) {
// dev_err(dev, "could not read vflip value\n");
// ret = -ENODEV;
// goto power_down;
//}
//
//ret = ov5645_read_reg(ov5645, OV5645_TIMING_TC_REG21,
// &ov5645->timing_tc_reg21);
//if (ret < 0) {
// dev_err(dev, "could not read hflip value\n");
// ret = -ENODEV;
// goto power_down;
//}

ov5645_s_power(&ov5645->sd, false);

memset(facing, 0, sizeof(facing));
if (strcmp(ov5645->module_facing, "back") == 0)
facing[0] = 'b';
else
facing[0] = 'f';

snprintf(ov5645->sd.name, sizeof(ov5645->sd.name), "m%02d_%s_%s %s",
ov5645->module_index, facing,
"ov5645", dev_name(ov5645->sd.dev));

ret = v4l2_async_register_subdev_sensor(&ov5645->sd);
if (ret) {
dev_err(dev, "v4l2 async register subdev failed\n");
}

#if 0
ret = v4l2_async_register_subdev(&ov5645->sd);
if (ret < 0) {
dev_err(dev, "could not register v4l2 device\n");
goto free_entity;
}
#endif

ov5645_entity_init_cfg(&ov5645->sd, NULL);

return 0;

power_down:
ov5645_s_power(&ov5645->sd, false);
free_entity:
media_entity_cleanup(&ov5645->sd.entity);
free_ctrl:
v4l2_ctrl_handler_free(&ov5645->ctrls);
mutex_destroy(&ov5645->power_lock);

return ret;
}

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/9 18:29:54

【稀缺技术指南】Open-AutoGLM中文编码问题破解:仅需调整这3个参数

第一章&#xff1a;Open-AutoGLM 中文输入乱码问题概述在使用 Open-AutoGLM 模型处理中文文本时&#xff0c;部分用户反馈在输入阶段出现中文字符显示为乱码的现象。该问题通常出现在数据预处理、模型加载或推理接口调用过程中&#xff0c;严重影响了中文语义的理解与生成质量。…

作者头像 李华
网站建设 2026/5/5 4:28:00

移动端动画架构终极指南:构建企业级组件化解决方案

移动端动画架构终极指南&#xff1a;构建企业级组件化解决方案 【免费下载链接】lottie-ios airbnb/lottie-ios: Lottie-ios 是一个用于 iOS 平台的动画库&#xff0c;可以将 Adobe After Effects 动画导出成 iOS 应用程序&#xff0c;具有高性能&#xff0c;易用性和扩展性强的…

作者头像 李华
网站建设 2026/5/9 21:43:52

5个VizTracer数据管理技巧:平衡性能与存储的终极指南

5个VizTracer数据管理技巧&#xff1a;平衡性能与存储的终极指南 【免费下载链接】viztracer VizTracer is a low-overhead logging/debugging/profiling tool that can trace and visualize your python code execution. 项目地址: https://gitcode.com/gh_mirrors/vi/viztr…

作者头像 李华
网站建设 2026/5/3 8:20:21

C++压缩算法实战指南:性能对比与最佳应用场景

C压缩算法实战指南&#xff1a;性能对比与最佳应用场景 【免费下载链接】awesome-cpp awesome-cpp - 一个精选的 C 框架、库、资源和有趣事物的列表。 项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-cpp 在当今数据驱动的时代&#xff0c;数据压缩已成为提…

作者头像 李华
网站建设 2026/5/6 20:53:37

CCC认证的好处有哪些?

CCC 认证是我国针对涉及安全、健康、环保的产品设立的强制性准入认证&#xff0c;获得该认证的好处可以从市场准入、经营风险、品牌价值、质量管控四个核心维度体现&#xff1a;合法进入市场的必备条件CCC 认证是对应目录内产品在国内生产、销售、进口的强制要求&#xff0c;没…

作者头像 李华
网站建设 2026/5/4 12:55:58

Java面试题及答案整理:JVM+Spring+MySQL+ 线程池 + 锁

就目前大环境来看&#xff0c;跳槽成功的难度比往年高很多。一个明显的感受&#xff1a;今年的面试&#xff0c;无论一面还是二面&#xff0c;都很考验Java程序员的技术功底。这不马上又到了面试跳槽的黄金段&#xff0c;成功升职加薪&#xff0c;不成功饱受打击。当然也要注意…

作者头像 李华