当前位置: 首页 > news >正文

rk3568制冷项目驱动开发流程汇总(只适用于部分模块CIF DVP等,自用)

采用fpga输入,3568采集并显示至hdmi

RKVICAP 驱动框架说明
        RKVICAP驱动主要是基于 v4l2 / media 框架实现硬件的配置、中断处理、控制 buffer 轮转,以及控制 subdevice(如 mipi dphy sensor) 的上下电等功能。
        对于RK356X 芯片而言, VICAP 只有单核,同时拥有 dvp/mipi 两种接口, dvp 接口对应一个 rkvicap_dvp 节点,mipi 接口对应一个 rkvicap_mipi_lvds 节点(与 RV1126/RV1109 VICAP FULL 同名),各节点可独立采集。
        为了将VICAP 采集数据信息同步给 isp 驱动,需要将 VICAP 驱动生成的逻辑 sditf 节点链接到 isp 所生成的虚拟节点设备。DVP 接口对应 rkvicap_dvp_sditf 节点, VICAP FULL mipi/lvds 接口对应 rkvicap_mipi_lvds_sditf节点, VICAP LITE 对应 rkvicap_lite_sditf

1.DVP camera

RK3568有一个DVP接口,支持BT601/BT656/BT1120等,同样的,如果是RAW的sensor,需要配置到ISP,如果是YUV的,则不需经过ISP,关键配置如下

(1)在sensor驱动的g_mbus_config接口中,通过flag指明当前sensor的hsync-acitve/vsyncactive/pclk-ative的有效极性,否则会导致无法收到数据;

static int avafpga_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id,struct v4l2_mbus_config *config)
{config->type = V4L2_MBUS_BT656;config->flags = V4L2_MBUS_HSYNC_ACTIVE_HIGH |V4L2_MBUS_VSYNC_ACTIVE_HIGH |V4L2_MBUS_PCLK_SAMPLE_RISING;return 0;
}
(2)设备树的节点中hsync-active/vsync-active 不要配置,否则 v4l2 框架异步注册时会识别为 BT601;
(3)pclk-sample/bus-width 可选;
bus-width = <16>;
pclk-sample = <1>;

(4)必须实现v4l2_subdev_video_ops中的querystd接口,指明当前接口为ATSC接口,否则会导致无法收到数据;

static int avafpga_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
{*std = V4L2_STD_ATSC;return 0;
}

(5)必须实现RKMODULE_GET_BT656_MBUS_INFOBT656/BT1120都是调用这个ioctl,接口兼容,实现参考drivers/media/i2c/nvp6158_drv/nvp6158_v4l2.c

static __maybe_unused void
avafpga_get_bt656_module_inf(struct avafpga *avafpga,struct rkmodule_bt656_mbus_info *inf)
{memset(inf, 0, sizeof(*inf));inf->flags = RKMODULE_CAMERA_BT656_PARSE_ID_LSB;switch (avafpga->ch_nums) {case 1:inf->flags |= RKMODULE_CAMERA_BT656_CHANNEL_0;break;case 2:inf->flags |= RKMODULE_CAMERA_BT656_CHANNEL_0 |RKMODULE_CAMERA_BT656_CHANNEL_1;break;case 4:inf->flags |= RKMODULE_CAMERA_BT656_CHANNELS;break;default:inf->flags |= RKMODULE_CAMERA_BT656_CHANNELS;}
}static long avafpga_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
{long ret = 0;switch (cmd) {default:ret = -ENOTTY;break;}return ret;
}#ifdef CONFIG_COMPAT
static long avafpga_compat_ioctl32(struct v4l2_subdev *sd,unsigned int cmd, unsigned long arg)
{long ret = 0;//struct rkmodule_bt656_mbus_info *bt565_inf;switch (cmd) {default:ret = -ENOIOCTLCMD;break;}return ret;
}
#endif#define DST_XPOS 0
#define DST_YPOS 0
#define DST_WIDTH 1536 //1920
#define DST_HEIGHT 576 //1080static int avafpga_get_selection(struct v4l2_subdev *sd,struct v4l2_subdev_pad_config *cfg,struct v4l2_subdev_selection *sel)
{if (sel->target == V4L2_SEL_TGT_CROP_BOUNDS) {sel->r.left = DST_XPOS;sel->r.top = DST_YPOS;sel->r.width = DST_WIDTH;sel->r.height = DST_HEIGHT;return 0;}return -EINVAL;
}static int avafpga_initialize_controls(struct avafpga *avafpga)
{int ret;struct v4l2_ctrl_handler *handler;const struct avafpga_mode *mode;u32 h_blank, v_blank;handler = &avafpga->ctrl_handler;mode = avafpga->cur_mode;ret = v4l2_ctrl_handler_init(handler, 2);if (ret)return ret;handler->lock = &avafpga->mutex;h_blank = mode->hts_def - mode->width;avafpga->hblank_ctrl = v4l2_ctrl_new_std(handler, NULL,V4L2_CID_HBLANK, h_blank, h_blank, 1, h_blank);v_blank = mode->vts_def - mode->height;avafpga->vblank_ctrl = v4l2_ctrl_new_std(handler, NULL,V4L2_CID_VBLANK, v_blank, v_blank, 1, v_blank);if (handler->error) {ret = handler->error;dev_err(&avafpga->client->dev,"Failed to init controls(%d)\n", ret);goto err_free_handler;}avafpga->subdev.ctrl_handler = handler;return 0;err_free_handler:v4l2_ctrl_handler_free(handler);return ret;
}static const struct v4l2_subdev_core_ops avafpga_core_ops = {.s_power = avafpga_s_power,.ioctl = avafpga_ioctl,
#ifdef CONFIG_COMPAT.compat_ioctl32 = avafpga_compat_ioctl32,
#endif
};

(6)pinctrl需要引用对,以对bt656/bt1120相关gpio做相应iomux,否则会导致无法收到数据。

dts 配置如下:
&i2c0 {status =  "okay";sensor@3c{status =  "okay";compatible = "firefly,pc9202";reg = <0x3c>;wd-en-gpio = <&gpio3 23 GPIO_ACTIVE_HIGH>;};avafpga: avafpga@32 {status = "okay";compatible = "ava,fpga";reg = <0x32>;clocks = <&cru CLK_CIF_OUT>;clock-names = "xvclk";power-domains = <&power RK3568_PD_VI>;pwdn-gpios = <&gpio4 RK_PB4 GPIO_ACTIVE_HIGH>;reset-gpios = <&gpio3 RK_PB6 GPIO_ACTIVE_HIGH>;rockchip,grf = <&grf>;pinctrl-names = "default";pinctrl-0 = <&cif_clk&cif_dvp_clk&cif_dvp_bus16&cif_dvp_bus8>;rockchip,camera-module-index = <0>;rockchip,camera-module-facing = "back";rockchip,camera-module-name = "default";rockchip,camera-module-lens-name = "default";rockchip,dvp_mode = "BT1120"; //BT656 or BT1120 or BT656_TESTport {cam_para_out2: endpoint {remote-endpoint = <&dvp_in_bcam>;bus-width = <16>;pclk-sample = <1>;};};};
};&rkcif {status = "okay";
};&rkcif_mmu {status = "okay";
};&rkcif_dvp {status = "okay";port {dvp_in_bcam: endpoint {remote-endpoint = <&cam_para_out2>;bus-width = <16>;};};
};

(7)/rk356x_sdk-linux5.10/kernel/drivers/media/i2c目录下增加fpga.c,并在kconfig和makefile中增加相关模块的设置

config VIDEO_FPGAtristate "AVA FPGA sensor support"depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_APIdepends on MEDIA_CAMERA_SUPPORThelpThis is a Video4Linux2 sensor driver for the AVAFPGA camera.To compile this driver as a module, choose M here: themodule will be called fpga.
obj-y += fpga.o

完整的fpga的c代码如下,亦可见附件(开始未设置ioctl,上电v4l2抓图时,打印_avafpga_start_stream enter然后崩掉,后经查阅资料以及参考rv1126的内容,加入对应的部分,可以成功获取数据,且不会崩掉)

#include <linux/clk.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
#include <linux/version.h>
#include <linux/rk-camera-module.h>
#include <media/media-entity.h>
#include <media/v4l2-async.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-subdev.h>
#include <linux/pinctrl/consumer.h>
#include <linux/rk-preisp.h>#include <media/v4l2-fwnode.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_graph.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/mfd/syscon.h>
#include <linux/version.h>#define DRIVER_VERSION			KERNEL_VERSION(0, 0x0, 0x01)
//#define PIX_FORMAT			MEDIA_BUS_FMT_UYVY8_2X8
#define PIX_FORMAT                    MEDIA_BUS_FMT_YUYV8_2X8
#define AVAFPGA_NAME			"avafpga"struct regval {u16 addr;u8 val;
};struct avafpga_mode {u32 width;u32 height;struct v4l2_fract max_fps;u32 hts_def;u32 vts_def;u32 exp_def;const struct regval *reg_list;
};struct avafpga {struct i2c_client	*client;struct clk		*xvclk;struct gpio_desc	*reset_gpio;struct gpio_desc	*pwdn_gpio;struct v4l2_subdev	subdev;struct media_pad	pad;struct v4l2_ctrl_handler ctrl_handler;struct v4l2_ctrl	*exposure;struct v4l2_ctrl	*anal_gain;struct v4l2_ctrl	*digi_gain;struct v4l2_ctrl	*hblank;struct v4l2_ctrl	*vblank;struct v4l2_ctrl	*test_pattern;struct mutex		mutex;bool			streaming;bool			power_on;const struct avafpga_mode *cur_mode;u32			module_index;const char		*module_facing;const char		*module_name;const char		*len_name;u32			ch_nums;//hjkstruct v4l2_ctrl	*vblank_ctrl;struct v4l2_ctrl	*hblank_ctrl;u8 is_reset;
};#define to_avafpga(sd) container_of(sd, struct avafpga, subdev)static const struct avafpga_mode supported_modes[] = {{//.width = 1920,//.height = 1080,.width = 1536,.height = 576,		.max_fps = {.numerator = 10000,.denominator = 600000,},.exp_def = 0x0100,.hts_def = 0x044c * 2,.vts_def = 0x0465,}
};static int __avafpga_start_stream(struct avafpga *avafpga)
{printk(KERN_ERR "%s enter\n", __func__);avafpga->is_reset = 1;//hjk1126printk(KERN_ERR "%s exit\n", __func__);//hjk1126return 0;
}static int __avafpga_stop_stream(struct avafpga *avafpga)
{printk(KERN_ERR "%s enter\n", __func__);return 0;
}static int avafpga_s_stream(struct v4l2_subdev *sd, int on)
{struct avafpga *avafpga = to_avafpga(sd);struct i2c_client *client = avafpga->client;int ret = 0;mutex_lock(&avafpga->mutex);on = !!on;if (on == avafpga->streaming)goto unlock_and_return;if (on) {ret = pm_runtime_get_sync(&client->dev);if (ret < 0) {pm_runtime_put_noidle(&client->dev);goto unlock_and_return;}ret = __avafpga_start_stream(avafpga);if (ret) {v4l2_err(sd, "start stream failed while write regs\n");pm_runtime_put(&client->dev);goto unlock_and_return;}} else {__avafpga_stop_stream(avafpga);pm_runtime_put(&client->dev);}avafpga->streaming = on;
unlock_and_return:mutex_unlock(&avafpga->mutex);return ret;
}#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
static int avafpga_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{struct avafpga *avafpga = to_avafpga(sd);struct v4l2_mbus_framefmt *try_fmt =v4l2_subdev_get_try_format(sd, fh->pad, 0);const struct avafpga_mode *def_mode = &supported_modes[0];mutex_lock(&avafpga->mutex);/* Initialize try_fmt */try_fmt->width = def_mode->width;try_fmt->height = def_mode->height;try_fmt->code = PIX_FORMAT;try_fmt->field = V4L2_FIELD_NONE;mutex_unlock(&avafpga->mutex);/* No crop or compose */return 0;
}
#endifstatic int avafpga_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id,struct v4l2_mbus_config *config)
{//config->type = V4L2_MBUS_BT656;//config->flags = V4L2_MBUS_PCLK_SAMPLE_RISING;config->type = V4L2_MBUS_BT656;config->flags = V4L2_MBUS_PCLK_SAMPLE_RISING;//config->flags = V4L2_MBUS_HSYNC_ACTIVE_LOW |//V4L2_MBUS_VSYNC_ACTIVE_LOW |//V4L2_MBUS_PCLK_SAMPLE_FALLING;//config->type = V4L2_MBUS_BT656;//config->flags = RKMODULE_CAMERA_BT656_CHANNELS |//V4L2_MBUS_PCLK_SAMPLE_RISING;//config->type = V4L2_MBUS_BT656;config->flags = V4L2_MBUS_HSYNC_ACTIVE_HIGH |V4L2_MBUS_VSYNC_ACTIVE_HIGH |V4L2_MBUS_PCLK_SAMPLE_RISING;return 0;}static int avafpga_g_frame_interval(struct v4l2_subdev *sd,struct v4l2_subdev_frame_interval *fi)
{struct avafpga *avafpga = to_avafpga(sd);const struct avafpga_mode *mode = avafpga->cur_mode;mutex_lock(&avafpga->mutex);fi->interval = mode->max_fps;mutex_unlock(&avafpga->mutex);return 0;
}static int avafpga_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
{*std = V4L2_STD_ATSC;return 0;
}static int avafpga_enum_frame_interval(struct v4l2_subdev *sd,struct v4l2_subdev_pad_config *cfg,struct v4l2_subdev_frame_interval_enum *fie)
{if (fie->index >= ARRAY_SIZE(supported_modes))return -EINVAL;//if (fie->code != PIX_FORMAT)//return -EINVAL;fie->width = supported_modes[fie->index].width;fie->height = supported_modes[fie->index].height;fie->interval = supported_modes[fie->index].max_fps;return 0;
}static int avafpga_enum_mbus_code(struct v4l2_subdev *sd,struct v4l2_subdev_pad_config *cfg,struct v4l2_subdev_mbus_code_enum *code)
{if (code->index != 0)return -EINVAL;code->code = PIX_FORMAT;return 0;
}static int avafpga_enum_frame_sizes(struct v4l2_subdev *sd,struct v4l2_subdev_pad_config *cfg,struct v4l2_subdev_frame_size_enum *fse)
{if (fse->index >= ARRAY_SIZE(supported_modes))return -EINVAL;//if (fse->code != PIX_FORMAT)//hjk1126中没有这个//return -EINVAL;//hjk1126中没有这个fse->min_width  = supported_modes[fse->index].width;fse->max_width  = supported_modes[fse->index].width;fse->max_height = supported_modes[fse->index].height;fse->min_height = supported_modes[fse->index].height;return 0;
}static int avafpga_set_fmt(struct v4l2_subdev *sd,struct v4l2_subdev_pad_config *cfg,struct v4l2_subdev_format *fmt)
{struct avafpga *avafpga = to_avafpga(sd);const struct avafpga_mode *mode;mutex_lock(&avafpga->mutex);mode = avafpga->cur_mode;fmt->format.code = PIX_FORMAT;fmt->format.width = mode->width;fmt->format.height = mode->height;fmt->format.field = V4L2_FIELD_NONE;//fmt->format.field = V4L2_FIELD_INTERLACED;if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API*v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format;
#elsemutex_unlock(&avafpga->mutex);return -ENOTTY;
#endif} else {avafpga->cur_mode = mode;}mutex_unlock(&avafpga->mutex);return 0;
}static int avafpga_get_fmt(struct v4l2_subdev *sd,struct v4l2_subdev_pad_config *cfg,struct v4l2_subdev_format *fmt)
{struct avafpga *avafpga = to_avafpga(sd);const struct avafpga_mode *mode = avafpga->cur_mode;mutex_lock(&avafpga->mutex);if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
#ifdef CONFIG_VIDEO_V4L2_SUBDEV_APIfmt->format = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
#elsemutex_unlock(&avafpga->mutex);return -ENOTTY;
#endif} else {fmt->format.width = mode->width;fmt->format.height = mode->height;fmt->format.code = PIX_FORMAT;fmt->format.field = V4L2_FIELD_NONE;}mutex_unlock(&avafpga->mutex);return 0;
}static int avafpga_s_power(struct v4l2_subdev *sd, int on)
{struct avafpga *avafpga = to_avafpga(sd);struct i2c_client *client = avafpga->client;int ret = 0;mutex_lock(&avafpga->mutex);/* If the power state is not modified - no work to do. */if (avafpga->power_on == !!on)goto unlock_and_return;if (on) {ret = pm_runtime_get_sync(&client->dev);if (ret < 0) {pm_runtime_put_noidle(&client->dev);goto unlock_and_return;}avafpga->power_on = true;} else {pm_runtime_put(&client->dev);avafpga->power_on = false;}unlock_and_return:mutex_unlock(&avafpga->mutex);return ret;
}static int __avafpga_power_on(struct avafpga *avafpga)
{return 0;
}static void __avafpga_power_off(struct avafpga *avafpga)
{return;
}static int avafpga_runtime_resume(struct device *dev)
{struct i2c_client *client = to_i2c_client(dev);struct v4l2_subdev *sd = i2c_get_clientdata(client);struct avafpga *avafpga = to_avafpga(sd);return __avafpga_power_on(avafpga);
}static int avafpga_runtime_suspend(struct device *dev)
{struct i2c_client *client = to_i2c_client(dev);struct v4l2_subdev *sd = i2c_get_clientdata(client);struct avafpga *avafpga = to_avafpga(sd);__avafpga_power_off(avafpga);return 0;
}hjk///
static __maybe_unused void
avafpga_get_bt656_module_inf(struct avafpga *avafpga,struct rkmodule_bt656_mbus_info *inf)
{memset(inf, 0, sizeof(*inf));inf->flags = RKMODULE_CAMERA_BT656_PARSE_ID_LSB;switch (avafpga->ch_nums) {case 1:inf->flags |= RKMODULE_CAMERA_BT656_CHANNEL_0;break;case 2:inf->flags |= RKMODULE_CAMERA_BT656_CHANNEL_0 |RKMODULE_CAMERA_BT656_CHANNEL_1;break;case 4:inf->flags |= RKMODULE_CAMERA_BT656_CHANNELS;break;default:inf->flags |= RKMODULE_CAMERA_BT656_CHANNELS;}
}static long avafpga_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
{long ret = 0;//struct avafpga *avafpga = to_avafpga(sd);switch (cmd) {/*case RKMODULE_GET_BT656_MBUS_INFO:avafpga_get_bt656_module_inf(avafpga,(struct rkmodule_bt656_mbus_info*)arg);break;*/default:ret = -ENOTTY;break;}return ret;
}#ifdef CONFIG_COMPAT
static long avafpga_compat_ioctl32(struct v4l2_subdev *sd,unsigned int cmd, unsigned long arg)
{//void __user *up = compat_ptr(arg);//struct rkmodule_inf *inf;//struct rkmodule_awb_cfg *cfg;//int *seq;long ret = 0;//struct rkmodule_bt656_mbus_info *bt565_inf;switch (cmd) {/*case RKMODULE_GET_BT656_MBUS_INFO:bt565_inf = kzalloc(sizeof(*bt565_inf), GFP_KERNEL);if (!bt565_inf) {ret = -ENOMEM;return ret;}ret = avafpga_ioctl(sd, cmd, bt565_inf);if (!ret) {ret = copy_to_user(up, bt565_inf, sizeof(*bt565_inf));if (ret)ret = -EFAULT;}kfree(bt565_inf);break;*/default:ret = -ENOIOCTLCMD;break;}return ret;
}
#endif#define DST_XPOS 0
#define DST_YPOS 0
#define DST_WIDTH 1536 //1920
#define DST_HEIGHT 576 //1080static int avafpga_get_selection(struct v4l2_subdev *sd,struct v4l2_subdev_pad_config *cfg,struct v4l2_subdev_selection *sel)
{if (sel->target == V4L2_SEL_TGT_CROP_BOUNDS) {sel->r.left = DST_XPOS;sel->r.top = DST_YPOS;sel->r.width = DST_WIDTH;sel->r.height = DST_HEIGHT;return 0;}return -EINVAL;
}static int avafpga_initialize_controls(struct avafpga *avafpga)
{int ret;struct v4l2_ctrl_handler *handler;const struct avafpga_mode *mode;u32 h_blank, v_blank;handler = &avafpga->ctrl_handler;mode = avafpga->cur_mode;ret = v4l2_ctrl_handler_init(handler, 2);if (ret)return ret;handler->lock = &avafpga->mutex;h_blank = mode->hts_def - mode->width;avafpga->hblank_ctrl = v4l2_ctrl_new_std(handler, NULL,V4L2_CID_HBLANK, h_blank, h_blank, 1, h_blank);v_blank = mode->vts_def - mode->height;avafpga->vblank_ctrl = v4l2_ctrl_new_std(handler, NULL,V4L2_CID_VBLANK, v_blank, v_blank, 1, v_blank);if (handler->error) {ret = handler->error;dev_err(&avafpga->client->dev,"Failed to init controls(%d)\n", ret);goto err_free_handler;}avafpga->subdev.ctrl_handler = handler;return 0;err_free_handler:v4l2_ctrl_handler_free(handler);return ret;
}
hjk//static const struct dev_pm_ops avafpga_pm_ops = {SET_RUNTIME_PM_OPS(avafpga_runtime_suspend,avafpga_runtime_resume, NULL)
};#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
static const struct v4l2_subdev_internal_ops avafpga_internal_ops = {.open = avafpga_open,
};
#endifstatic const struct v4l2_subdev_core_ops avafpga_core_ops = {.s_power = avafpga_s_power,//hjk.ioctl = avafpga_ioctl,
#ifdef CONFIG_COMPAT.compat_ioctl32 = avafpga_compat_ioctl32,
#endif//hjk
};static const struct v4l2_subdev_video_ops avafpga_video_ops = {.s_stream = avafpga_s_stream,.g_frame_interval = avafpga_g_frame_interval,.querystd = avafpga_querystd,
};static const struct v4l2_subdev_pad_ops avafpga_pad_ops = {.enum_mbus_code = avafpga_enum_mbus_code,.enum_frame_size = avafpga_enum_frame_sizes,.enum_frame_interval = avafpga_enum_frame_interval,.get_fmt = avafpga_get_fmt,.set_fmt = avafpga_set_fmt,.get_selection = avafpga_get_selection,.get_mbus_config = avafpga_g_mbus_config,
};static const struct v4l2_subdev_ops avafpga_subdev_ops = {.core	= &avafpga_core_ops,.video	= &avafpga_video_ops,.pad	= &avafpga_pad_ops,
};static int avafpga_probe(struct i2c_client *client,const struct i2c_device_id *id)
{struct device *dev = &client->dev;struct avafpga *avafpga;struct v4l2_subdev *sd;char facing[2];int ret;dev_info(dev, "driver version: %02x.%02x.%02x",DRIVER_VERSION >> 16,(DRIVER_VERSION & 0xff00) >> 8,DRIVER_VERSION & 0x00ff);avafpga = devm_kzalloc(dev, sizeof(*avafpga), GFP_KERNEL);if (!avafpga)return -ENOMEM;avafpga->client = client;avafpga->cur_mode = &supported_modes[0];avafpga->xvclk = devm_clk_get(dev, "xvclk");if (IS_ERR(avafpga->xvclk)) {dev_err(dev, "Failed to get xvclk\n");return -EINVAL;}//avafpga->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);//if (IS_ERR(avafpga->reset_gpio))//dev_warn(dev, "Failed to get reset-gpios\n");//avafpga->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW);//if (IS_ERR(avafpga->pwdn_gpio))//dev_warn(dev, "Failed to get pwdn-gpios\n");mutex_init(&avafpga->mutex);sd = &avafpga->subdev;v4l2_i2c_subdev_init(sd, client, &avafpga_subdev_ops);//hjkret = avafpga_initialize_controls(avafpga);if (ret) {dev_err(dev, "Failed to initialize controls fpga\n");goto err_free_handler;}//hjkret = __avafpga_power_on(avafpga);if (ret)goto err_free_handler;#ifdef CONFIG_VIDEO_V4L2_SUBDEV_APIsd->internal_ops = &avafpga_internal_ops;sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |V4L2_SUBDEV_FL_HAS_EVENTS;
#endif#if defined(CONFIG_MEDIA_CONTROLLER)avafpga->pad.flags = MEDIA_PAD_FL_SOURCE;sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;ret = media_entity_pads_init(&sd->entity, 1, &avafpga->pad);if (ret < 0)goto err_power_off;
#endifmemset(facing, 0, sizeof(facing));if (!sd->dev)dev_err(dev, "sd dev is null\n");snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s",avafpga->module_index, facing,AVAFPGA_NAME, dev_name(sd->dev));ret = v4l2_async_register_subdev_sensor_common(sd);if (ret) {dev_err(dev, "v4l2 async register subdev failed\n");goto err_clean_entity;}pm_runtime_set_active(dev);pm_runtime_enable(dev);pm_runtime_idle(dev);dev_err(dev, "v4l2 async register subdev sucessfully\n");return 0;err_clean_entity:
#if defined(CONFIG_MEDIA_CONTROLLER)media_entity_cleanup(&sd->entity);
#endif
err_power_off:__avafpga_power_off(avafpga);
err_free_handler:v4l2_ctrl_handler_free(&avafpga->ctrl_handler);mutex_destroy(&avafpga->mutex);return ret;
}static int avafpga_remove(struct i2c_client *client)
{struct v4l2_subdev *sd = i2c_get_clientdata(client);struct avafpga *avafpga = to_avafpga(sd);v4l2_async_unregister_subdev(sd);
#if defined(CONFIG_MEDIA_CONTROLLER)media_entity_cleanup(&sd->entity);
#endifv4l2_ctrl_handler_free(&avafpga->ctrl_handler);mutex_destroy(&avafpga->mutex);pm_runtime_disable(&client->dev);if (!pm_runtime_status_suspended(&client->dev))__avafpga_power_off(avafpga);pm_runtime_set_suspended(&client->dev);return 0;
}#if IS_ENABLED(CONFIG_OF)
static const struct of_device_id avafpga_of_match[] = {{ .compatible = "ava,fpga" },{},
};
MODULE_DEVICE_TABLE(of, avafpga_of_match);
#endifstatic const struct i2c_device_id avafpga_match_id[] = {{"ava,fpga", 0 },{},
};static struct i2c_driver avafpga_i2c_driver = {.driver = {.name = AVAFPGA_NAME,.of_match_table = of_match_ptr(avafpga_of_match),},.probe		= &avafpga_probe,.remove		= &avafpga_remove,.id_table	= avafpga_match_id,
};static int __init sensor_mod_init(void)
{return i2c_add_driver(&avafpga_i2c_driver);
}static void __exit sensor_mod_exit(void)
{i2c_del_driver(&avafpga_i2c_driver);
}device_initcall_sync(sensor_mod_init);
module_exit(sensor_mod_exit);MODULE_DESCRIPTION("AVA FPGA sensor driver");
MODULE_LICENSE("GPL v2");

编译后会在路径下生成fpga.o,加载进内核模块

具体的调试结果如下

 

 

相关文章:

rk3568制冷项目驱动开发流程汇总(只适用于部分模块CIF DVP等,自用)

采用fpga输入&#xff0c;3568采集并显示至hdmi RKVICAP 驱动框架说明 RKVICAP驱动主要是基于 v4l2 / media 框架实现硬件的配置、中断处理、控制 buffer 轮转&#xff0c;以及控制 subdevice(如 mipi dphy 及 sensor) 的上下电等功能。 对于RK356X 芯片而言&#xff0c; VICAP…...

EMC——射频场感应的传导骚扰抗扰度(CS)

术语和定义 AE&#xff08;辅助设备&#xff09; 为受试设备正常运行提供所需信号的设备和检验受试设备性能的设备&#xff1b; 钳注入 是用电缆上的钳合式“电流”注入装置获得的钳注入&#xff1b; 电流钳 由被注入信号的电缆构成的二次绕组实现的电流变换器&#xff1b; 电磁…...

postgreSql对分钟级的降雨数据进行插值为整小时

postgreSql对分钟级的降雨数据进行插值为整小时 SQL语句实现 SQL语句实现 --核查某个小流域的降雨量小时插值是否正确SELECT tm, sum(drp) as sum, round(sum(drp), 2) as drp2 from(SELECT a.stcd, (TO_TIMESTAMP(time_period, YYYY-MM-DD HH24:MI:SS) INTERVAL 1 HOUR) as t…...

如何安全获取股票实时数据API并在服务器运行?

以下是安全获取股票实时数据 API 并在服务器运行的方法&#xff1a; 选择合适的券商或交易平台 评估自身需求&#xff1a;明确自己的交易策略、交易品种、交易频率等需求&#xff0c;以及对 股票api 的功能、性能、稳定性等方面的要求。调研券商或平台&#xff1a;了解不同券商…...

Android Bootable Recovery 中的 `imgdiff.cpp` 文件解析

Android Bootable Recovery 中的 imgdiff.cpp 文件解析 引言 在 Android 系统中,Recovery 模式是一个非常重要的组成部分,它允许用户在设备无法正常启动时进行系统修复、数据恢复、OTA 更新等操作。其中,OTA(Over-The-Air)更新是 Android 系统中常见的更新方式,它通过网…...

golang学习笔记-变量与常量

1.标识符 在编程语言中标识符就是程序员定义的具有特殊意义的词,比如变量名,常量名,函数名等.go语言中标识符有字母数字和_(下划线)组成,并且只能以字母和_开头 2.关键字 关键字是指变成语言中预先定义好的特殊含义的标识符 break default func interface select case …...

关于变分量子算法的问答

1.零噪声外推如何通过增加误差的过程来改善估计的误差缓解类型? 解释&#xff1a;**零噪声外推&#xff08;ZNE&#xff09;**是一种误差缓解方法&#xff0c;通过故意增加噪声并利用这些增加噪声的结果来改进量子电路的估计。其核心思想是在不同的噪声级别下运行量子电路&am…...

小学数学思维训练 一年级 第一周(少儿思维启蒙)

前言 本文主要介绍了通过各种题型和解题方法培养孩子的数学思维能力。通过系统的方法训练一年级学生的数学思维能力&#xff0c;帮助他们学会举一反三&#xff0c;融会贯通地解决各类数学问题。 点击获取小学数学1-6年级思维训练电子版 第一周 比一比 比一比是实际生活中常…...

sqlite 自定以脚本解释器

应用程序使用 libfdt 解析设备树,获取兼容性配置 内核源码支持libfdt 标准设备树语法,不用自己再创造 非常的爽,因为设备树支持预编译 一些可以跑类 BSD 系统的设备也可以使用这样的方法,不仅仅是在linux 系统上跑 有pylibfdt 支持解析设备树&#xff0c;校验设备树是否是正确的…...

动手学深度学习11.2. 凸性-笔记练习(PyTorch)

本节课程地址&#xff1a;72 优化算法【动手学深度学习v2】_哔哩哔哩_bilibili 本节教材地址&#xff1a;11.2. 凸性 — 动手学深度学习 2.0.0 documentation 本节开源代码&#xff1a;...>d2l-zh>pytorch>chapter_multilayer-perceptrons>convexity.ipynb 凸性 …...

go并发模型的详细介绍

Go 语言的并发模型是其一大亮点&#xff0c;它使得并发编程变得简单高效。Go 语言并发模型的核心概念是 goroutines 和 channels。在理解这两个概念之前&#xff0c;我们首先了解并发编程的一些基本概念。 1. 并发与并行 并发&#xff08;Concurrency&#xff09;&#xff1a;…...

使用FreeNAS软件部署ISCSI的SAN架构存储(IP-SAN)练习题

一&#xff0c;实验用到工具分别为&#xff1a; VMware虚拟机&#xff0c;安装教程&#xff1a;VMware Workstation Pro 17 安装图文教程 FreeNAS系统&#xff0c;安装教程&#xff1a;FreeNAS-11.2-U4.1安装教程2024&#xff08;图文教程&#xff09; 二&#xff0c;新建虚…...

FreeSWITCH实现多人电话会议功能

FreeSWITCH实现多人电话会议功能 作者&#xff1a;基于Java与FreeSWITCH的开源呼叫中心系统FreeIPCC FreeSWITCH作为一个开源的电话软交换平台&#xff0c;为企业和运营商提供了构建高效、灵活的语音通信系统的能力。其中&#xff0c;多人电话会议功能是其核心应用之一&#…...

Chromium 中chrome.webRequest扩展接口定义c++

一、chrome.webRequest 注意&#xff1a;从 Manifest V3 开始&#xff0c;"webRequestBlocking"权限不再适用于大多数扩展程序。以"declarativeNetRequest"为例&#xff0c;它允许使用declarativeNetRequest API。除了"webRequestBlocking"之外…...

极乐 15.2.6 | 清爽版简约美观音乐软件,支持网易云歌单导入

极乐是一款使用起来非常轻松的音乐播放软件&#xff0c;它拥有清新简洁的画面&#xff0c;专注于音乐播放功能。最新版本全面升级了64位架构&#xff0c;带来了前所未有的性能提升和更稳定的体验。通过优化内存管理&#xff0c;降低了应用对系统资源的占用&#xff0c;确保设备…...

如何在 Ubuntu 22.04 上安装 Graylog 开源日志管理平台

简介 Graylog 的开源特性、丰富的功能、灵活性和可扩展性使其成为一个流行的日志管理平台。在本教程中&#xff0c;我将向你展示如何在 Ubuntu 22.04 上安装 Graylog&#xff0c;包括配置 Graylog 服务器软件包和访问 Graylog Web UI。 Graylog 是什么&#xff1f; Graylog …...

Wux weapp 组件库的 bug—— wux-picker选择器组件无法正确初始化到选定的value

options的value为Number&#xff0c;组件无法正常使用 解决方案&#xff0c;修改picker-view/utils.js中的getIndexFromValue函数&#xff0c;如下&#xff1a; export function getIndexFromValue(value, col [], fieldNames DEFAULT_FIELD_NAMES) {//return getRealIndex(…...

决策树(理论知识1)

目录 何为决策树决策树的组成决策树的构建 何为决策树 决策树(Decision Tree)是一种分类和回归方法&#xff0c;是基于各种情况发生的所需条件构成决策树&#xff0c;以实现期望最大化的一种图解法。由于这种决策 分支画成图形很像一棵树的枝干&#xff0c;故称决策树。它的运…...

【Spring】获取Bean对象需要哪些注解

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01; 希望本文内容能够帮助到你&#xff01;&#xff01; 目录 一&#xff1a;Service&#xff08;服务存储&#xff09; 1&#xff1a;存储bean的代码 2&#xff1…...

java的Webclient对象怎解解析400状态码

在Java中使用WebClient处理400状态码&#xff0c;可以通过检查响应状态并根据状态码进行相应的错误处理。以下是几种处理400状态码的方法&#xff1a; 使用onStatus方法判断和处理错误&#xff1a; 你可以使用WebClient的retrieve()方法链中的onStatus方法来检查响应状态码。如…...

【计算机视觉基础CV-图像分类】03-深度学习图像分类实战:鲜花数据集加载与预处理详解

本文将深入介绍鲜花分类数据集的加载与处理方式&#xff0c;同时详细解释代码的每一步骤并给出更丰富的实践建议和拓展思路。以实用为导向&#xff0c;为读者提供从数据组织、预处理、加载到可视化展示的完整过程&#xff0c;并为后续模型训练打下基础。 前言 在计算机视觉的深…...

ubuntu 如何重装你的apt【apt-get报错: symbol lookup error/undefined symbol】

副标题:解决error:apt-get: symbol lookup error: /lib/x86_64-linux-gnu/libapt-private.so.0.0: undefined symbol: _ZNK13pkgTagSection7FindULLENS_3KeyERKy, version APTPKG_6.0 文章目录 问题描述报错分析解决方案:重装你的apt1、查看你的ubuntu版本2、下载适配你的ap…...

Unity 上好用的插件

PlayerMaker BehaviorDesigner Cinemachine Timeline Hybrid Addressable AssetBundle Blower Simple Zoom 大地图上缩放和平移使用ScrollRect的好效果实现...

大数据机器学习算法和计算机视觉应用07:机器学习

Machine Learning Goal of Machine LearningLinear ClassificationSolutionNumerical output example: linear regressionStochastic Gradient DescentMatrix Acceleration Goal of Machine Learning 机器学习的目标 假设现在有一组数据 x i , y i {x_i,y_i} xi​,yi​&…...

Godot RPG 游戏开发指南

Godot RPG 游戏开发指南 一、基础准备 1. 开发环境 下载并安装最新版 Godot 4.x选择使用 GDScript 或 C# 作为开发语言准备基础美术资源&#xff08;角色、地图、道具等&#xff09; 2. 项目结构 project/ ├── scenes/ # 场景文件 ├── scripts/ # 脚…...

c++ 找第一个只出现一次的字符

【题目描述】 给定一个只包含小写字母的字符串&#xff0c;请你找到第一个仅出现一次的字符。如果没有&#xff0c;输出no。 【输入】 一个字符串&#xff0c;长度小于100000。 【输出】 输出第一个仅出现一次的字符&#xff0c;若没有则输出no。 【输入样例】 abcabd【输出样…...

时空信息平台架构搭建:基于netty封装TCP通讯模块(IdleStateHandler网络连接监测,处理假死)

文章目录 引言I 异步TCP连接操作II 心跳机制:空闲检测(读空闲和写空闲)基于Netty的IdleStateHandler类实现心跳机制(网络连接监测)常规的处理假死健壮性的处理假死方案获取心跳指令引言 基于netty实现TCP客户端:封装断线重连、连接保持 https://blog.csdn.net/z92911896…...

【Rust自学】3.6. 控制流:循环

3.6.0. 写在正文之前 欢迎来到Rust自学的第三章&#xff0c;一共有6个小节&#xff0c;分别是: 变量与可变性数据类型&#xff1a;标量类型数据类型&#xff1a;复合类型函数和注释控制流&#xff1a;if else控制流&#xff1a;循环&#xff08;本文&#xff09; 通过第二章…...

如何正确计算显示器带宽需求

1. 对显示器的基本认识 一个显示器的参数主要有这些&#xff1a; 分辨率&#xff1a;显示器屏幕上像素点的总数&#xff0c;通常用横向像素和纵向像素的数量来表示&#xff0c;比如19201080&#xff08;即1080p&#xff09;。 刷新率&#xff1a;显示器每秒钟画面更新的次数&…...

mysql 基于chunk机制是如何支持运行期间,动态调整buffer pool大小的

mysql 基于chunk机制是如何支持运行期间&#xff0c;动态调整buffer pool大小的 MySQL 的 InnoDB 存储引擎确实支持在运行期间动态调整缓冲池&#xff08;buffer pool&#xff09;的大小&#xff0c;但其机制与自定义缓存系统有所不同。InnoDB 通过内部优化和配置参数来实现这…...

梳理你的思路(从OOP到架构设计)_简介设计模式

目录 1、 模式(Pattern) 是较大的结构​编辑 2、 结构形式愈大 通用性愈小​编辑 3、 从EIT造形 组合出设计模式 1、 模式(Pattern) 是较大的结构 组合与创新 達芬奇說&#xff1a;簡單是複雜的終極形式 (Simplicity is the ultimate form of sophistication) —Leonardo d…...

【Redis】缓存

什么是缓存 https://tech.meituan.com/2017/03/17/cache-about.html Spring Data Redis Spring Data Redis提供了从Spring应用程序轻松配置和访问Redis的功能。 引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>sp…...

基于 PyCharm 和 Navicat 的新闻管理系统

# 用于创建连接池 pip3 install mysql-connector-python # 改变终端打印颜色 pip3 install colorama 1.创建连接池 文件地址&#xff1a;db/mysql_db.py 首先建立一个与 MySQL 数据库的连接池&#xff0c;以便在应用程序中复用连接&#xff0c;提高性能。 如果连接池创建失败…...

<QNAP 453D QTS-5.x> 日志记录: 优化性能 内存管理 修改swap优先顺序 swap放在ssd 网络稳定性 进程出错管理

起因 几个月前&#xff0c;开始重学编程&#xff0c;往 NAS 的 docker 里放了些 containers &#xff0c;每一个用来跑练习的 App。为了放更多的app&#xff0c;上个月加了 4GB 内存。最近只放了两个&#xff0c;NAS 就会时不时的闪断。codes 全存在网络驱动器上&#xff0c;当…...

一区牛顿-拉夫逊算法+分解+深度学习!VMD-NRBO-Transformer-GRU多变量时间序列光伏功率预测

一区牛顿-拉夫逊算法分解深度学习&#xff01;VMD-NRBO-Transformer-GRU多变量时间序列光伏功率预测 目录 一区牛顿-拉夫逊算法分解深度学习&#xff01;VMD-NRBO-Transformer-GRU多变量时间序列光伏功率预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.中科院一区…...

本地部署webrtc应用怎么把http协议改成https协议?

环境&#xff1a; WSL2 Ubuntu22.04 webrtc视频聊天应用 问题描述&#xff1a; 本地部署webrtc应用怎么把http协议改成https协议&#xff1f; http协议在安卓手机浏览器上用不了麦克风本&#xff0c;来地应用webrtc 本来是http协议&#xff0c;在安卓手机上浏览器不支持使…...

React简单了解

原理简化了解 import React from "react" import { createRoot } form "react-dom/client"const element React.createElement(p,{id: hello},Hello World! )const container document.querySelector(#root) const root createRoot(container) root.r…...

基于LabVIEW的USRP信道测量开发

随着无线通信技术的不断发展&#xff0c;基于软件无线电的设备&#xff08;如USRP&#xff09;在信道测量、无线通信测试等领域扮演着重要角色。通过LabVIEW与USRP的结合&#xff0c;开发者可以实现信号生成、接收及信道估计等功能。尽管LabVIEW提供了丰富的信号处理工具和图形…...

Docker挂载

目录 数据卷挂载 本地目录挂载 数据卷挂载 宿主机默认的存放所有容器数据卷的目录&#xff1a;/var/lib/docker/volumes nginx容器 静态文件目录&#xff1a;/usr/share/nginx/html 配置文件目录&#xff1a;/etc/nginx/nginx.conf 修改宿主机的内容&#xff0c;进入到容器查…...

使用Java结合经纬度位置计算目标点的日出日落时间

目录 前言 一、应用示例 1、天安门升旗时间 2、湖南省日出日落信息 二、JAVA日出日落计算 1、在线API 2、使用Java进行计算 三、总结 前言 随着城市化进程的加速&#xff0c;城市环境与人类生活的联系日益紧密。城市不仅承载着居住、工作、休闲等多种功能&#xff0c;也…...

八字精批api接口_php获取生成八字和批注的方法研究

八字算命 API 介绍 这个八字算命 API 提供了一种便捷的方式&#xff0c;让用户通过 GET 或 POST 请求获取详细的八字信息。API 返回的数据格式为 JSON&#xff0c;包含多种命理分析和建议&#xff0c;适合对传统命理学感兴趣的用户。 API 功能 五行分析&#xff1a; 提供用户…...

docker run 命令参数

user docker run -it --nameubn18 --gpus all --privilegedtrue --shm-size 8G ubuntu:18.04 /bin/bash-it 是什么意思 4o 在运行 docker run 命令时&#xff0c;-it 是两个选项的组合&#xff0c;用于更好地与容器进行交互&#xff1a; -i 或 --interactive&#xff1a;这个选…...

智能外呼技术如何改变企业营销方式

智能外呼技术如何改变企业营销方式 作者&#xff1a;开源大模型智能呼叫中心系统FreeAICC&#xff0c;Github&#xff1a;https://github.com/FreeIPCC/FreeAICC 在数字化时代&#xff0c;企业营销方式正经历着前所未有的变革。其中&#xff0c;智能外呼技术作为一项前沿的人…...

redis数据转移

可能有时候因为硬件的原因我们我们需要更换服务器&#xff0c;如果更换服务器的话&#xff0c;那我们redis的数据该怎样转移呢&#xff0c;按照一下步骤即可完成redis数据的转移 1.进入redis客户端 2.使用 bgsave命令进行数据的备份&#xff0c;此命令完成后会在你的redis安装目…...

STM32-笔记5-按键点灯(中断方法)

1、复制03-流水灯项目&#xff0c;重命名06-按键点灯&#xff08;中断法&#xff09; 在\Drivers\BSP目录下创建一个文件夹exti&#xff0c;在该文件夹下&#xff0c;创建两个文件exti.c和exti.h文件&#xff0c;并且把这两个文件加载到项目中&#xff0c;打开项目工程文件 加载…...

DotNetBrowser 3.0.0 正式发布!

&#x1f6e0;️ 重要消息&#xff1a;DotNetBrowser 3.0.0 正式发布&#xff01; 我们很高兴向您介绍全新的 DotNetBrowser 3.0.0 版本。此次更新带来了多项重要功能与优化&#xff0c;进一步提升了 Web 开发的效率和体验。 &#x1f4e2; DotNetBrowser 3.0.0 包含哪些新功…...

MySQL基础笔记(三)

在此特别感谢尚硅谷-康师傅的MySQL精品教程 获取更好的阅读体验请前往我的博客主站! 如果本文对你的学习有帮助&#xff0c;请多多点赞、评论、收藏&#xff0c;你们的反馈是我更新最大的动力&#xff01; 创建和管理表 1. 基础知识 1.1 一条数据存储的过程 存储数据是处理数…...

SEO初学者-搜索引擎如何工作

搜索引擎基础搜索引擎是如何建立索引的搜索引擎如何对网页进行排名搜索引擎是如何个性化搜索结果的 搜索引擎的工作方式是使用网络爬虫抓取数十亿个页面。爬虫也称为蜘蛛或机器人&#xff0c;它们在网络上导航并跟踪链接以查找新页面。然后&#xff0c;这些页面会被添加到搜索引…...

在Ubuntu下运行QEMU仿真FreeBSD riscv64系统

在Ubuntu下运行QEMU仿真FreeBSD riscv64系统 突发奇想&#xff0c;尝试在Ubuntu下运行QEMU仿真FreeBSD riscv64系统&#xff0c; 参考这篇文档&#xff1a;手把手教你在QEMU上运行RISC-V Linux_qemu 运行 .bin-CSDN博客 并参考FreeBSD的Wiki&#xff1a;riscv - FreeBSD Wik…...

SQL 使用带聚集函数的联结

聚集函数用于汇总数据&#xff0c;通常用于从一个表中计算统计信息&#xff0c;但也可以与联结一起使用。以下是一个例子&#xff0c;展示如何使用聚集函数统计每个顾客的订单数。 示例 1&#xff1a;使用 COUNT() 函数与 INNER JOIN 假设我们需要检索所有顾客及每个顾客所下…...