当前位置: 首页 > 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…...

费舍尔信息矩阵全面讲述

费舍尔信息矩阵&#xff08;Fisher Information Matrix&#xff09; 费舍尔信息矩阵是统计学中一个非常重要的概念&#xff0c;尤其在参数估计、最大似然估计&#xff08;MLE&#xff09;和贝叶斯推断中具有广泛的应用。它反映了参数估计的不确定性程度&#xff0c;也可以用来…...

DALFox-一款XSS自动化扫描工具

声明&#xff01;本文章所有的工具分享仅仅只是供大家学习交流为主&#xff0c;切勿用于非法用途&#xff0c;如有任何触犯法律的行为&#xff0c;均与本人及团队无关&#xff01;&#xff01;&#xff01; 目录标题 一、介绍及使用启动及使用1. 单个扫描2. 多个扫描3. 文件扫描…...

Python 异步协程:从 async/await 到 asyncio 再到 async with

在 Python 3.8 以后的版本中&#xff0c;异步编程变得越来越重要。本文将系统介绍 Python 标准库中的异步编程工具&#xff0c;带领大家掌握 async/await 语法和 asyncio 的使用。 从一个简单的场景开始 假设我们在处理一些耗时的 I/O 操作&#xff0c;比如读取多个文件或处理…...

云原生周刊:利用 eBPF 增强 K8s

开源项目推荐 Slurm-operator Slurm-operator 是一个高效可扩展的框架&#xff0c;用于在 K8s 环境中部署和运行 Slurm 工作负载。 它结合了 Slurm 的可靠性和 Kubernetes 的灵活性&#xff0c;支持快速部署 Slurm 集群、动态扩展 HPC 工作负载&#xff0c;并提供高度灵活的定…...

【pycharm】远程服务器之后如何打开终端

【pycharm】远程服务器之后如何打开终端 在pycharm中&#xff0c;我们通过远程连接服务器&#xff0c;此时如果我们需要在终端运行的话&#xff0c;并不能直接在本地终端运行&#xff0c;而是需要连接到服务器终端才能运行命令 设置如下&#xff1a; 输入服务器的ip、端口、…...

从零创建一个 Django 项目

1. 准备环境 在开始之前&#xff0c;确保你的开发环境满足以下要求&#xff1a; 安装了 Python (推荐 3.8 或更高版本)。安装 pip 包管理工具。如果要使用 MySQL 或 PostgreSQL&#xff0c;确保对应的数据库已安装。 创建虚拟环境 在项目目录中创建并激活虚拟环境&#xff…...

无人零售 4G 工业无线路由器赋能自助贩卖机高效运营

工业4G路由器为运营商赋予 “千里眼”&#xff0c;实现对贩卖机销售、库存、设备状态的远程精准监控&#xff0c;便于及时补货与维护&#xff1b;凭借强大的数据实时传输&#xff0c;助力深度洞察销售趋势、优化库存、挖掘商机&#xff1b;还能远程升级、保障交易安全、快速处理…...

使用VSCode Debugger 调试 React项目

一般我们调试代码时&#xff0c;用的最多的应该就是console.log方式了&#xff0c;还有的是使用Chrome DevTools 通过在对应的 sourcemap代码位置打断点进行调试&#xff0c;除了上面两种方式外还有一种更好用的调试方式&#xff1a; VSCode Debugger。 VSCode Debugger可以直…...

[创业之路-199]:《华为战略管理法-DSTE实战体系》- 3 - 价值转移理论与利润区理论

目录 一、价值转移理论 1.1. 什么是价值&#xff1f; 1.2. 什么价值创造 &#xff08;1&#xff09;、定义 &#xff08;2&#xff09;、影响价值创造的因素 &#xff08;3&#xff09;、价值创造的三个过程 &#xff08;4&#xff09;、价值创造的实践 &#xff08;5&…...

AWTK-WEB 快速入门(2) - JS 应用程序

AWTK 可以使用相同的技术栈开发各种平台的应用程序。有时我们需要使用 Web 界面与设备进行交互&#xff0c;本文介绍一下如何使用 JS 语言开发 AWTK-WEB 应用程序。 用 AWTK Designer 新建一个应用程序 先安装 AWTK Designer&#xff1a; https://awtk.zlg.cn/web/index.html…...

dolphinscheduler服务注册中心源码解析(三)RPC提供者服务整合注册中心注册服务实现源码

RPC提供者服务整合注册中心注册服务实现源码 1.概述2.源码解读思路3.实现2.1.应用服务的RPC服务接口定义2.1.1.MasterServer应用中提供的RPC接口服务2.1.2.WorkerServer应用中提供的RPC接口服务2.2.应用服务的RPC服务接口实现2.2.1.MasterServer应用中提供的RPC接口服务实现类2…...

电脑不小心删除了msvcr120.dll文件怎么办?“缺失msvcr120.dll文件”要怎么解决?

一、文件丢失与损坏的常见原因及解决办法 1. 不小心删除系统文件 常见情况&#xff1a;有时在清理电脑垃圾文件时&#xff0c;可能会不小心删除一些重要的系统文件&#xff0c;如msvcr120.dll等。解决办法&#xff1a; 恢复文件&#xff1a;如果刚删除不久&#xff0c;可以尝…...

js 深度克隆

深度克隆&#xff08;Deep Clone&#xff09;是指复制一个对象或数组及其所有嵌套结构的副本&#xff0c;使得克隆后的对象与原对象完全独立。JavaScript 提供了一些方法实现深度克隆&#xff0c;但每种方法有其优缺点。 1. 常用方法 1.1 使用 JSON.parse 和 JSON.stringify …...

深度学习之超分辨率算法——FRCNN

– 对之前SRCNN算法的改进 输出层采用转置卷积层放大尺寸&#xff0c;这样可以直接将低分辨率图片输入模型中&#xff0c;解决了输入尺度问题。改变特征维数&#xff0c;使用更小的卷积核和使用更多的映射层。卷积核更小&#xff0c;加入了更多的激活层。共享其中的映射层&…...

软件测试之压力测试【详解】

压力测试 压力测试是一种软件测试&#xff0c;用于验证软件应用程序的稳定性和可靠性。压力测试的目标是在极其沉重的负载条件下测量软件的健壮性和错误处理能力&#xff0c;并确保软件在危急情况下不会崩溃。它甚至可以测试超出正常工作点的测试&#xff0c;并评估软件在极端…...

电脑出现 0x0000007f 蓝屏问题怎么办,参考以下方法尝试解决

电脑蓝屏是让许多用户头疼的问题&#xff0c;其中出现 “0x0000007f” 错误代码更是较为常见且棘手。了解其背后成因并掌握修复方法&#xff0c;能帮我们快速恢复电脑正常运行。 一、可能的硬件原因 内存问题 内存条长时间使用可能出现物理损坏&#xff0c;如金手指氧化、芯片…...

分布式系统架构:限流设计模式

1.为什么要限流&#xff1f; 任何一个系统的运算、存储、网络资源都不是无限的&#xff0c;当系统资源不足以支撑外部超过预期的突发流量时&#xff0c;就应该要有取舍&#xff0c;建立面对超额流量自我保护的机制&#xff0c;而这个机制就是微服务中常说的“限流” 2.四种限流…...

G口带宽服务器与1G独享带宽服务器:深度剖析其差异

在数据洪流涌动的数字化时代&#xff0c;服务器作为数据处理的核心&#xff0c;其性能表现直接关系到业务的流畅度和用户体验的优劣。随着技术的飞速发展&#xff0c;G口带宽服务器与1G独享带宽服务器已成为众多企业的优选方案。然而&#xff0c;这两者之间究竟有何细微差别&am…...

Flamingo:少样本多模态大模型

Flamingo&#xff1a;少样本多模态大模型 论文大纲理解1. 确认目标2. 分析过程&#xff08;目标-手段分析&#xff09;3. 实现步骤4. 效果展示5. 金手指 解法拆解全流程核心模式提问Flamingo为什么选择使用"固定数量的64个视觉tokens"这个特定数字?这个数字的选择背…...

推荐一款免费且好用的 国产 NAS 系统 ——FnOS

一、系统基础信息 开发基础&#xff1a;基于最新的Linux内核&#xff08;Debian发行版&#xff09;深度开发&#xff0c;兼容主流x86硬件&#xff08;ARM还没适配&#xff09;&#xff0c;自由组装NAS&#xff0c;灵活扩展外部存储。 使用情况&#xff1a;官方支持功能较多&am…...

2025系统架构师(一考就过):案例题之一:嵌入式架构、大数据架构、ISA

一、嵌入式系统架构 软件脆弱性是软件中存在的弱点(或缺陷)&#xff0c;利用它可以危害系统安全策略&#xff0c;导致信息丢失、系统价值和可用性降低。嵌入式系统软件架构通常采用分层架构&#xff0c;它可以将问题分解为一系列相对独立的子问题&#xff0c;局部化在每一层中…...

开机存活脚本

vim datastadard_alive.sh #!/bin/bashPORT18086 # 替换为你想要检查的端口号 dt$(date %Y-%m-%d)# 使用netstat检查端口是否存在 if netstat -tuln | grep -q ":$PORT"; thenecho "$dt Port $PORT is in use" > /opt/datastadard/logs/alive.log# 如…...

车载网关性能 --- GW ECU报文(message)处理机制的技术解析

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所谓鸡汤,要么蛊惑你认命,要么怂恿你拼命,但都是回避问题的根源,以现象替代逻辑,以情绪代替思考,把消极接受现实的懦弱,伪装成乐观面对不幸的…...

CosyVoice安装过程详解

CosyVoice安装过程详解 安装过程参考官方文档 前情提要 环境&#xff1a;Windows子系统WSL下安装的Ubunt22.4python环境管理&#xff1a;MiniConda3git 1. Clone代码 $ git clone --recursive https://github.com/FunAudioLLM/CosyVoice.git # 若是submodule下载失败&…...

传统网络架构与SDN架构对比

传统网络采用分布式控制&#xff0c;每台设备独立控制且管理耗时耗力&#xff0c;扩展困难&#xff0c;按 OSI 模型分层&#xff0c;成本高、业务部署慢、安全性欠佳且开放性不足。而 SDN 架构将控制平面集中到控制器&#xff0c;数据转发由交换机负责&#xff0c;可统一管理提…...

如何打造用户友好的维护页面:6个创意提升WordPress网站体验

在网站运营中&#xff0c;无论是个人博主还是大型企业网站的管理员&#xff0c;难免会遇到需要维护的情况。无论是服务器迁移、插件更新&#xff0c;还是突发的技术故障&#xff0c;都可能导致网站短暂无法访问。这时&#xff0c;设计维护页面能很好的缓解用户的不满&#xff0…...

【hackmyvm】Zday靶机wp

HMVrbash绕过no_root_squash静态编译fogproject 1. 基本信息^toc 这里写目录标题 1. 基本信息^toc2. 信息收集2.1. 端口扫描2.2. 目录扫描 3. fog project Rce3.1. ssh绕过限制 4. NFS no_root_squash5. bash运行不了怎么办 靶机链接 https://hackmyvm.eu/machines/machine.ph…...

redis使用注意哪些事项

1. 数据类型选择&#xff1a; • Redis支持多种数据类型&#xff0c;如字符串&#xff08;String&#xff09;、哈希&#xff08;Hash&#xff09;、列表&#xff08;List&#xff09;、集合&#xff08;Set&#xff09;、有序集合&#xff08;Sorted Set&#xff09;等。在选择…...

步进电机位置速度双环控制实现

步进电机位置速度双环控制实现 野火stm32电机教学 提高部分-第11讲 步进电机位置速度双环控制实现(1)_哔哩哔哩_bilibili PID模型 位置环作为外环,速度环作为内环。设定目标位置和实际转轴位置的位置偏差,经过位置PID获得位置期望,然后讲位置期望(位置变化反映了转轴的速…...