解决 gst-launch-1.0 指令死机的问题

This commit is contained in:
hehaoyang 2024-01-08 06:52:00 +00:00
parent c2fbbc1566
commit 52cb12348b
2 changed files with 110 additions and 58 deletions

162
kernel/drivers/media/i2c/chipup/xs9922.c Normal file → Executable file
View File

@ -1,12 +1,3 @@
// SPDX-License-Identifier: GPL-2.0
/*
* xs9922 driver
*
* Copyright (C) 2021 Rockchip Electronics Co., Ltd.
*
* V0.0X01.0X00 first version.
*/
#define DEBUG
#include <linux/clk.h>
#include <linux/device.h>
@ -67,6 +58,15 @@
#define XS9922_SET_FMT \
_IOR('V', BASE_VIDIOC_PRIVATE + 32, struct v4l2_subdev_format )
#define XS9922_SET_FMT_A \
_IOR('V', BASE_VIDIOC_PRIVATE + 31, struct v4l2_subdev_format )
#define XS9922_SET_FMT_B \
_IOR('V', BASE_VIDIOC_PRIVATE + 30, struct v4l2_subdev_format )
#define XS9922_SET_FMT_END \
_IOR('V', 0, struct v4l2_subdev_format )
enum xs9922_chip_stage {
STAGE_MIDDLE,
STAGE_LAST,
@ -136,6 +136,10 @@ struct xs9922 {
struct v4l2_ctrl *link_freq;
struct mutex mutex;
bool power_on;
bool power_on_first;
bool power_on_sec;
bool power_on_third;
bool power_on_four;
struct xs9922_mode cur_mode;
u32 module_index;
@ -149,6 +153,11 @@ struct xs9922 {
bool lost_video_status;
#if (!__CLOSE_SENSOR__)
struct delayed_work delay_init;
struct delayed_work delay_init_first;
struct delayed_work delay_init_sec;
struct delayed_work delay_init_third;
struct delayed_work delay_init_four;
int delayed_time;
#endif
int chip_stage;
@ -386,23 +395,26 @@ void switch_mode(struct xs9922 *xs9922)
int ret = 0;
struct i2c_client *client = xs9922->client;
dev_dbg(&client->dev, "%s IN --->>>\n", __func__);
dev_err(&client->dev, "%s IN --->>>\n", __func__);
xs9922_write_array(client, xs9922->cur_mode.global_reg_list);
xs9922_write_array(client, xs9922->cur_mode.global_reg_list);
ret = xs9922_write_array(client, xs9922->cur_mode.reg_list);
if (ret)
{
dev_dbg(&client->dev, "%s write xs9922 register array error!\n", __func__);
dev_err(&client->dev, "%s write xs9922 register array error!\n", __func__);
}
}
#if (!__CLOSE_SENSOR__)
static void __maybe_unused __xs9922_init(struct work_struct *work)
{
struct xs9922 *xs9922 = container_of(work, struct xs9922, delay_init.work);
struct delayed_work *dwork = to_delayed_work(work);
struct xs9922 *xs9922 = container_of(dwork, struct xs9922,
delay_init);
switch_mode(xs9922);
}
#endif
static int xs9922_get_reso_dist(const struct xs9922_mode *mode,
@ -573,6 +585,19 @@ static int xs9922_enum_frame_interval(struct v4l2_subdev *sd,
return 0;
}
static int xs9922_g_frame_interval(struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *fi)
{
struct xs9922 *xs9922 = to_xs9922(sd);
const struct xs9922_mode *mode = &xs9922->cur_mode;
mutex_lock(&xs9922->mutex);
fi->interval = mode->max_fps;
mutex_unlock(&xs9922->mutex);
return 0;
}
static int xs9922_g_mbus_config(struct v4l2_subdev *sd,
struct v4l2_mbus_config *cfg)
{
@ -580,7 +605,7 @@ static int xs9922_g_mbus_config(struct v4l2_subdev *sd,
struct i2c_client *client = xs9922->client;
const struct xs9922_mode *mode = &xs9922->cur_mode;
dev_dbg(&client->dev, "mode->lanes = %d\n", mode->lanes);
dev_dbg(&client->dev, "chapin mode->lanes = %d\n", mode->lanes);
cfg->flags = V4L2_MBUS_CSI2_4_LANE |
V4L2_MBUS_CSI2_CONTINUOUS_CLOCK |
@ -625,21 +650,11 @@ static __maybe_unused int xs9922_auto_detect_hotplug(struct xs9922 *xs9922)
xs9922_read_reg(client, 0x0e10, XS9922_REG_VALUE_08BIT, &tmp9);
xs9922_read_reg(client, 0x0e08, XS9922_REG_VALUE_08BIT, &tmp10);
dev_err(&xs9922->client->dev, "%s: auto detect: %d\n", __func__,
dev_dbg(&xs9922->client->dev, "%s: auto detect: %d\n", __func__,
(val0 & 0x01) | (val1 & 0x01) << 1 | (val2 & 0x01) << 2 | (val3 & 0x01) << 3);
dev_err(&xs9922->client->dev, "%s: ch0: %x , ch1: %x , ch2: %x ch3: %x\n", __func__,
val0, val1, val2,val3 );
dev_err(&xs9922->client->dev, "%s: 0x0803: %x , 0x1803: %x , 0x2803: %x 0x0805: %x, 0x1805:%x, 0x2805:%x, 0x4200:%x 0x4210:%x 0x4220:%x\n", __func__,
tmp0, tmp1, tmp2,tmp3, tmp4, tmp5, tmp6,tmp7,tmp8 );
dev_err(&xs9922->client->dev, "%s: 0x0e10:%x 0x0e08:%x", __func__, tmp9, tmp10);
//dev_err(&xs9922->client->dev, "Ch0 is %s\n", (val0 & 0x01) ? "Online ": "Offline");
//dev_err(&xs9922->client->dev, "Ch1 is %s\n", (val1 & 0x01) ? "Online ": "Offline");
// /dev_dbg(&xs9922->client->dev, "Ch0 is %s\n", (val0 & 0x01) ? "Online ": "Offline");
// /dev_dbg(&xs9922->client->dev, "Ch1 is %s\n", (val1 & 0x01) ? "Online ": "Offline");
// /dev_dbg(&xs9922->client->dev, "Ch2 is %s\n", (val2 & 0x01) ? "Online ": "Offline");
// /dev_dbg(&xs9922->client->dev, "Ch3 is %s\n", (val3 & 0x01) ? "Online ": "Offline");
@ -691,26 +706,38 @@ static long xs9922_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
struct xs9922 *xs9922 = to_xs9922(sd);
long ret = 0;
u32 stream = 0;
dev_err(&xs9922->client->dev, "%s IN --->>> cmd:0x%x\n", __func__, cmd);
//xs9922_auto_detect_hotplug(xs9922);
//dev_err(&xs9922->client->dev, "%s IN --->>> cmd:0x%x set_fmt = 0x%x quick_stream = 0x%x\n", __func__, cmd, (int) XS9922_SET_FMT, (int) RKMODULE_SET_QUICK_STREAM);
//dev_err(&xs9922->client->dev, "%s IN --->>> cmd:0x%x set_fmt = 0x%x quick_stream = 0x%x A = 0x%x B = 0x%x E = 0x%x format size = 0x%x\n", __func__, cmd, (int) XS9922_SET_FMT, (int) RKMODULE_SET_QUICK_STREAM, (int) XS9922_SET_FMT_A,(int) XS9922_SET_FMT_B, (int) XS9922_SET_FMT_END, (int) sizeof(struct v4l2_subdev_format));
if(cmd == 0xc00456e1) {
xs9922->power_on = 0;
dev_err(&xs9922->client->dev, "zwt ene\n");
if ((*(int *)arg) == 0)
xs9922->power_on_first = 0;
else if ((*(int *)arg) == 1)
xs9922->power_on_sec = 0;
else if ((*(int *)arg) == 2)
xs9922->power_on_third = 0;
else if ((*(int *)arg) == 3)
xs9922->power_on_four = 0;
dev_err(&xs9922->client->dev, "zwt ene %d\n", (*(int *)arg));
}
switch (cmd) {
case RKMODULE_GET_MODULE_INFO:
dev_err(&xs9922->client->dev, "get module info");
xs9922_get_module_inf(xs9922, (struct rkmodule_inf *)arg);
dev_err(&xs9922->client->dev, "module info\n");
break;
case RKMODULE_GET_VC_HOTPLUG_INFO:
dev_err(&xs9922->client->dev, "vc hotplug info");
xs9922_get_vc_hotplug_inf(xs9922, (struct rkmodule_vc_hotplug_info *)arg);
dev_err(&xs9922->client->dev, "[chad]Get VC Hotplug info --->>> detect status: %d\n",xs9922->detect_status);
break;
case RKMODULE_GET_VICAP_RST_INFO:
dev_err(&xs9922->client->dev, "vicap rst info");
xs9922_get_vicap_rst_inf(xs9922, (struct rkmodule_vicap_reset_info *)arg);
dev_err(&xs9922->client->dev, "[chad] Get vicap reset info --->>> is_reset : %d\n", xs9922->is_reset);
break;
@ -721,18 +748,19 @@ static long xs9922_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
break;
case RKMODULE_GET_START_STREAM_SEQ:
dev_err(&xs9922->client->dev, "stream seq");
*(int *)arg = RKMODULE_START_STREAM_FRONT;
break;
case XS9922_SET_FMT:
{
const struct xs9922_mode *mode;
mode = xs9922_find_best_fit(xs9922, (struct v4l2_subdev_format *) arg);
memcpy(&xs9922->cur_mode, mode, sizeof(struct xs9922_mode));
dev_err(&xs9922->client->dev, "xs9922_ioctl!\n");
#if (!__CLOSE_SENSOR__)
switch_mode(xs9922);
#endif
case XS9922_SET_FMT:
{
const struct xs9922_mode *mode;
mode = xs9922_find_best_fit(xs9922, (struct v4l2_subdev_format *) arg);
memcpy(&xs9922->cur_mode, mode, sizeof(struct xs9922_mode));
dev_err(&xs9922->client->dev, "xs9922_ioctl!\n");
#if (!__CLOSE_SENSOR__)
switch_mode(xs9922);
#endif
}
break;
#if 1
@ -787,6 +815,7 @@ static long xs9922_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
#endif
default:
//dev_err(&xs9922->client->dev, "chapin defalut cmd");
ret = -ENOTTY;
break;
}
@ -1049,6 +1078,8 @@ static int xs9922_stream(struct v4l2_subdev *sd, int on)
if (xs9922->streaming == on)
goto unlock;
dev_dbg(&client->dev, "chapin xs9922_stream call");
if (on) {
__xs9922_start_stream(xs9922);
} else {
@ -1079,25 +1110,41 @@ static int xs9922_power(struct v4l2_subdev *sd, int on)
if (xs9922->power_on == !!on)
goto exit;
dev_dbg(&client->dev, "%s: on %d\n", __func__, on);
if (on) {
ret = pm_runtime_get_sync(&client->dev);
if (ret < 0) {
pm_runtime_put_noidle(&client->dev);
goto exit;
}
#if (!__CLOSE_SENSOR__)
dev_dbg(&client->dev, "%s: >>>>>> global reg list and module reg list download...\n", __func__);
INIT_DELAYED_WORK(&xs9922->delay_init, __xs9922_init);
schedule_delayed_work(&xs9922->delay_init, msecs_to_jiffies(0));
if (xs9922->power_on_first == 0) {
dev_err(&client->dev, "%s: >>>>>> global reg list and module reg list download...\n", __func__);
INIT_DELAYED_WORK(&xs9922->delay_init, __xs9922_init);
schedule_delayed_work(&xs9922->delay_init, msecs_to_jiffies(0));
xs9922->power_on_first = 1;
dev_err(&client->dev, "%s: >>>>>> global reg list and module reg list download OK!\n", __func__);
}else if (xs9922->power_on_sec == 0) {
//dev_err(&client->dev, "%s: >>>>>> global reg list and module reg list download...\n", __func__);
//INIT_DELAYED_WORK(&xs9922->delay_init_sec, __xs9922_init_sec);
//schedule_delayed_work(&xs9922->delay_init_sec, msecs_to_jiffies(0));
//dev_err(&client->dev, "%s: >>>>>> global reg list and module reg list download OK!\n", __func__);
}else if (xs9922->power_on_third == 0) {
//dev_err(&client->dev, "%s: >>>>>> global reg list and module reg list download...\n", __func__);
//INIT_DELAYED_WORK(&xs9922->delay_init_sec, __xs9922_init_sec);
//schedule_delayed_work(&xs9922->delay_init_sec, msecs_to_jiffies(1));
//INIT_DELAYED_WORK(&xs9922->delay_init_third, __xs9922_init_third);
//schedule_delayed_work(&xs9922->delay_init_third, msecs_to_jiffies(0));
//dev_err(&client->dev, "%s: >>>>>> global reg list and module reg list download OK!\n", __func__);
}else if (xs9922->power_on_four == 0) {
//dev_err(&client->dev, "%s: >>>>>> global reg list and module reg list download...\n", __func__);
//INIT_DELAYED_WORK(&xs9922->delay_init_four, __xs9922_init_four);
//schedule_delayed_work(&xs9922->delay_init_four, msecs_to_jiffies(1));
//dev_err(&client->dev, "%s: >>>>>> global reg list and module reg list download OK!\n", __func__);
}
dev_dbg(&client->dev, "%s: >>>>>> global reg list and module reg list download OK!\n", __func__);
if (!xs9922_reg_config) {
xs9922_reg_config = true;
}
if (!xs9922_reg_config) {
xs9922_reg_config = true;
}
#endif
xs9922->power_on = true;
} else {
@ -1120,7 +1167,7 @@ static int __xs9922_power_on(struct xs9922 *xs9922)
struct device *dev = &xs9922->client->dev;
dev_dbg(dev, "%s\n", __func__);
printk("__xs9922_power_on\n");
printk("__xs9922_power_on xs9922->power_on = %d\n", xs9922->power_on);
#if (!__CLOSE_SENSOR__)
if (xs9922->power_on ) return 0;
#endif
@ -1178,9 +1225,9 @@ err_clk:
static void __xs9922_power_off(struct xs9922 *xs9922)
{
struct device *dev = &xs9922->client->dev;
printk("__xs9922_power_off\n");
pr_err("__xs9922_power_off called");
#if __CLOSE_SENSOR__
#if __CLOSE_SENSOR__ //modify by chapin
int ret;
if (!IS_ERR(xs9922->reset_gpio))
@ -1329,7 +1376,7 @@ static int xs9922_runtime_suspend(struct device *dev)
struct i2c_client *client = to_i2c_client(dev);
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct xs9922 *xs9922 = to_xs9922(sd);
dev_dbg(&client->dev, "%s \n",__func__);
dev_err(&client->dev, "%s \n",__func__);
__xs9922_power_off(xs9922);
@ -1355,7 +1402,9 @@ static int xs9922_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
try_fmt->code = def_mode->bus_fmt;
try_fmt->field = V4L2_FIELD_NONE;
printk("[ma] %s:%d width:%d height = %d\n", __func__, __LINE__, def_mode->width,def_mode->height);
xs9922->delayed_time = 0;
xs9922->power_on = 0;
pr_err("[ma] %s:%d width:%d height = %d xs9922->delayed_time = %d\n", __func__, __LINE__, def_mode->width,def_mode->height, xs9922->delayed_time);
mutex_unlock(&xs9922->mutex);
/* No crop or compose */
@ -1372,6 +1421,7 @@ static const struct v4l2_subdev_internal_ops xs9922_internal_ops = {
static const struct v4l2_subdev_video_ops xs9922_video_ops = {
.s_stream = xs9922_stream,
.g_frame_interval = xs9922_g_frame_interval,
.g_mbus_config = xs9922_g_mbus_config,
};
@ -1994,6 +2044,8 @@ static int xs9922_remove(struct i2c_client *client)
#if defined(CONFIG_MEDIA_CONTROLLER)
media_entity_cleanup(&sd->entity);
#endif
pr_err("xs9922_remove called");
cancel_delayed_work(&xs9922->delay_init);
v4l2_ctrl_handler_free(&xs9922->ctrl_handler);
mutex_destroy(&xs9922->mutex);

0
kernel/drivers/media/i2c/chipup/xs9922_reg_cfg.h Normal file → Executable file
View File