HDMI 调试之输出RGB888

news/2025/3/17 20:55:33/

(仅作记录,rk3588平台)

        RGB888这种数据格式可以被csi或dsi接收,驱动代码里默认是被dsi接收,但我们经常会遇到hdmi输出rgb888到mipi csi,所以需要在驱动中增加对csi接口的支持。

        首先了解下回调函数 v4l2_subdev_call,参数介绍以及定义如下:

/*** v4l2_subdev_call - call an operation of a v4l2_subdev.** @sd: pointer to the &struct v4l2_subdev* @o: name of the element at &struct v4l2_subdev_ops that contains @f.*     Each element there groups a set of callbacks functions.* @f: callback function to be called.*     The callback functions are defined in groups, according to*     each element at &struct v4l2_subdev_ops.* @args: arguments for @f.** Example: err = v4l2_subdev_call(sd, video, s_std, norm);*/
#define v4l2_subdev_call(sd, o, f, args...)			   \({								                   \struct v4l2_subdev *__sd = (sd);			   \int __result;						           \if (!__sd)						               \__result = -ENODEV;				           \else if (!(__sd->ops->o && __sd->ops->o->f))   \__result = -ENOIOCTLCMD;			       \else if (v4l2_subdev_call_wrappers.o &&		   \v4l2_subdev_call_wrappers.o->f)		   \__result = v4l2_subdev_call_wrappers.o->f( \__sd, ##args);	           \else							               \__result = __sd->ops->o->f(__sd, ##args);  \__result;						               \})

        对于rgb888是要使用csi接口还是dsi接口呢? 这就是根据实际来确认,我们调试hdmi需要输出rgb到csi,那么在hdmi驱动中需要在ioctl里添加case 用来判断dsi与csi;假设这个case命名为RKMODULE_RGB888_GET_CSI_DSI_INFO,则在 kernel-5.10/include/uapi/linux/rk-camera-module.h 参考其它模块进行添加;

#define RKMODULE_GET_CSI_DPHY_PARAM       \_IOWR('V', BASE_VIDIOC_PRIVATE + 32, struct rkmodule_csi_dphy_param)/* 定义一个新的case */
#define RKMODULE_RGB888_GET_CSI_DSI_INFO       \_IOWR('V', BASE_VIDIOC_PRIVATE + 33, __u32)

         那么在hdmi驱动中添加如下:

static long lt6911uxc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
{struct lt6911uxc *lt6911uxc = to_state(sd);long ret = 0;switch (cmd) {case RKMODULE_GET_MODULE_INFO:lt6911uxc_get_module_inf(lt6911uxc, (struct rkmodule_inf *)arg);break;// 添加一个case case RKMODULE_RGB888_GET_CSI_DSI_INFO:*(int *)arg = RKMODULE_CSI_INPUT;  // 自己定义的break;default:ret = -ENOIOCTLCMD;break;}return ret;
}static long lt6911uxc_compat_ioctl32(struct v4l2_subdev *sd,unsigned int cmd, unsigned long arg)
{int *seq;...........switch (cmd) {...........case RKMODULE_RGB888_GET_CSI_DSI_INFO:seq = kzalloc(sizeof(*seq), GFP_KERNEL);if (!seq) {ret = -ENOMEM;return ret;}ret = lt6911uxc_ioctl(sd, cmd, seq);if (!ret) {ret = copy_to_user(up, seq, sizeof(*seq));if (ret)ret = -EFAULT;}kfree(seq);break;..........return ret;
}

        上面ioctl中的RKMODULE_CSI_INPUT也是自己在rk-camera-module.h文件中定义的,如下所示;

/** CSI/DSI input select IOCTL*/
enum rkmodule_csi_dsi_seq {RKMODULE_CSI_INPUT = 0,RKMODULE_DSI_INPUT,
};

        那么在cif驱动中如何调用新添加的这个case呢?首先要知道数据先经过mipi csi2然后再传入cif控制器的;因此在mipi csi2驱动里也需要增加对csi与dsi的判断,那首先就要定义个函数用来获得我们接入的sensor,如下

kernel-5.10\drivers\media\platform\rockchip\cif\mipi-csi2.cstatic void get_remote_terminal_sensor(struct v4l2_subdev *sd,struct v4l2_subdev **sensor_sd)
{struct media_graph graph;struct media_entity *entity = &sd->entity;struct media_device *mdev = entity->graph_obj.mdev;int ret;/* Walk the graph to locate sensor nodes. */mutex_lock(&mdev->graph_mutex);ret = media_graph_walk_init(&graph, mdev);if (ret) {mutex_unlock(&mdev->graph_mutex);*sensor_sd = NULL;return;}media_graph_walk_start(&graph, entity);while ((entity = media_graph_walk_next(&graph))) {if (entity->function == MEDIA_ENT_F_CAM_SENSOR)break;}mutex_unlock(&mdev->graph_mutex);media_graph_walk_cleanup(&graph);if (entity)*sensor_sd = media_entity_to_v4l2_subdev(entity);else*sensor_sd = NULL;
}

          看下v4l2_subdev结构体的定义,路径kernel/include/media/v4l2-subdev.h,上面那个函数主要是解析media拓扑结构,来获取sensor的entity。

struct v4l2_subdev {
#if defined(CONFIG_MEDIA_CONTROLLER)struct media_entity entity;
#endifstruct list_head list;struct module *owner;bool owner_v4l2_dev;u32 flags;struct v4l2_device *v4l2_dev;const struct v4l2_subdev_ops *ops;const struct v4l2_subdev_internal_ops *internal_ops;struct v4l2_ctrl_handler *ctrl_handler;char name[V4L2_SUBDEV_NAME_SIZE];u32 grp_id;void *dev_priv;void *host_priv;struct video_device *devnode;struct device *dev;struct fwnode_handle *fwnode;struct list_head async_list;struct v4l2_async_subdev *asd;struct v4l2_async_notifier *notifier;struct v4l2_async_notifier *subdev_notifier;struct v4l2_subdev_platform_data *pdata;
};

        获取终端的sensor之后,那就要在csi2_update_sensor函数中获取sensor的最新状态,也就是获取rgb888数据是接入csi还是dsi;

kernel-5.10\drivers\media\platform\rockchip\cif\mipi-csi2.cstatic void csi2_update_sensor_info(struct csi2_dev *csi2)
{.............struct v4l2_subdev *terminal_sensor_sd = NULL;.............get_remote_terminal_sensor(&csi2->sd, &terminal_sensor_sd);ret = v4l2_subdev_call(terminal_sensor_sd, core, ioctl,RKMODULE_GET_CSI_DSI_INFO, &csi2->dsi_input_en);if (ret) {v4l2_dbg(1, csi2_debug, &csi2->sd, "get CSI/DSI sel failed, default csi!\n");csi2->dsi_input_en = 0;}............}

        v4l2_subdev_call中的参数是怎么选择的,像core,ioctl;其实上面刚才有介绍,可以看下hdmi驱动就知道了

//在 core 这个ops中,调用ioctl
static const struct v4l2_subdev_core_ops lt6911uxc_core_ops = {.interrupt_service_routine = lt6911uxc_isr,.subscribe_event = lt6911uxc_subscribe_event,.unsubscribe_event = v4l2_event_subdev_unsubscribe,.ioctl = lt6911uxc_ioctl,
#ifdef CONFIG_COMPAT.compat_ioctl32 = lt6911uxc_compat_ioctl32,
#endif
};

        执行完回调函数后,就知道了rgb888是csi接收的,但在这还增加了判断;

kernel-5.10\drivers\media\platform\rockchip\cif\mipi-csi2.cstatic int csi2_start(struct csi2_dev *csi2)
{............csi2_update_sensor_info(csi2);if (csi2->dsi_input_en == RKMODULE_DSI_INPUT)host_type = RK_DSI_RXHOST;elsehost_type = RK_CSI_RXHOST;.............
}kernel-5.10\drivers\media\platform\rockchip\cif\mipi-csi2.hstruct csi2_dev {struct device		*dev;............const char		*dev_name;int			dsi_input_en; //增加这个变量
};

        mipi csi修改完后,接下来就是cif驱动了,和mipi csi的修改一样,加入对csi和dsi的判断

kernel-5.10\drivers\media\platform\rockchip\cif\capture.c//回调函数,更新sensor的状态,确定接口
int rkcif_update_sensor_info(struct rkcif_stream *stream)
{..........terminal_sensor = &stream->cifdev->terminal_sensor;get_remote_terminal_sensor(stream, &terminal_sensor->sd);..........if (v4l2_subdev_call(terminal_sensor->sd, core, ioctl, RKMODULE_GET_CSI_DSI_INFO,&terminal_sensor->dsi_input_en)) {v4l2_dbg(1, rkcif_debug, &stream->cifdev->v4l2_dev,"%s: get terminal %s CSI/DSI sel failed, default csi input!\n",__func__, terminal_sensor->sd->name);terminal_sensor->dsi_input_en = 0;}.........
}static int rkcif_csi_channel_init(struct rkcif_stream *stream,struct csi_channel_info *channel)
{struct rkcif_device *dev = stream->cifdev;..........channel->cmd_mode_en = 0; /* default use DSI Video Mode */channel->dsi_input = dev->terminal_sensor.dsi_input_en;..........channel->data_type = get_data_type(stream->cif_fmt_in->mbus_code,channel->cmd_mode_en,channel->dsi_input);..........
}static unsigned char get_data_type(u32 pixelformat, u8 cmd_mode_en, u8 dsi_input)
{.............case MEDIA_BUS_FMT_RGB888_1X24:if (dsi_input) {     //dsi_input 自己定义添加if (cmd_mode_en) /* dsi command mode*/return 0x39;else /* dsi video mode */return 0x3e;} else {return 0x24;}............
}kernel-5.10\drivers\media\platform\rockchip\cif\dev.hstruct rkcif_sensor_info {struct v4l2_subdev *sd;struct v4l2_mbus_config mbus;struct v4l2_subdev_frame_interval fi;int lanes;struct v4l2_rect raw_rect;struct v4l2_subdev_selection selection;int dsi_input_en;  //自己定义的
};


http://www.ppmy.cn/news/197611.html

相关文章

白光FX-888D 温度初始化 350度

1.先关机 2.同时按 “UP” 和“ENTER” 并开机, 3.当面板显示"A" 时, 4.按下“ENTER” 就进入自我调节到350度

解决——imread.exe 中的 0x757da832 处有未经处理的异常: Microsoft C++ 异常: 内存位置 0x0052f888 处的 cv::Exception。

出现上图错误提示,问题基本是图片路径的问题。应将程序相应的图像放置在工程目录下(和cpp源文件同一目录下)。

0x757da832 处有未经处理的异常: Microsoft C++ 异常: 内存位置 0x0052f888 处的 cv::Exception。

opencv新手,没把图片放到相应的目录里面,读不到图片。把将被处理的图片放到与含有main函数的cpp文件相同的目录中。

JSBridge 原理

JSBridge 的起源 近些年,移动端普及化越来越高,开发过程中选用 Native 还是 H5 一直是热门话题。Native 和 H5 都有着各自的优缺点,为了满足业务的需要,公司实际项目的开发过程中往往会融合两者进行 Hybrid 开发。Native 和 H5 分…

旧改快讯--桑泰南山桃源“工改商住”项目规划修改

南山区桃源街道西丽同富裕工业城城市更新单元原列入《2019年深圳市南山区城市更新单元计划第一批计划》,后进行更新方向调整,列入《2020年深圳市南山区城市更新单元计划第三批计划》,2022年8月发布实施主体公示,实施主体为深圳市桑…

oracle数据文件恢复步骤

1、基于linux操作系统文件恢复 条件:1、误强制删除linux下的数据文件(rm -rf)。2、未重启数据库或操作系统。3、数据库是归档模式 恢复原理:句柄恢复文件–因为我们的操作系统是linux,当数据文件从操作系统级别被rm掉…

1. 爬虫及爬虫的步骤

1. 爬虫及爬虫的步骤 文章目录 1. 爬虫及爬虫的步骤1. 爬虫是什么?2. 爬虫的作用3. 爬虫步骤3.1 获取网页3.2 解析网页3.3 存储数据 4. 总结 1. 爬虫是什么? 爬虫就是写一段代码让计算机模仿人类自动访问网站。 2. 爬虫的作用 爬虫可以代替人们自动地…

nova7se乐活版升级鸿蒙,华为nova7se乐活版和普通版区别参数对比 哪个性价比高

今天小编为大家带来最新的华为nova7SE乐活版和华为nova7SE的参数对比,那么这两款手机在性能方面哪款手机更好?有什么区别?小编为大家带来最新的手机资讯,快来看看吧。 一、参数对比 二、区别分析 1、性能方面 华为nova7SE乐活版&a…