From 133c9be08fc7d496e76edb7dca5ff4e9c85fdb4e Mon Sep 17 00:00:00 2001 From: jiabinhe Date: Fri, 1 Nov 2024 18:09:40 +0800 Subject: [PATCH 1/2] driver: fix S3 issue Signed-off-by: jiabinhe --- drivers/media/i2c/imx390.c | 20 +------------------- drivers/media/i2c/isx031.c | 19 +------------------ drivers/media/i2c/ti960-des.c | 15 +++++++++++++++ 3 files changed, 17 insertions(+), 37 deletions(-) diff --git a/drivers/media/i2c/imx390.c b/drivers/media/i2c/imx390.c index 7bb4c5a19a7c..97b60993b361 100644 --- a/drivers/media/i2c/imx390.c +++ b/drivers/media/i2c/imx390.c @@ -1681,27 +1681,9 @@ static int __maybe_unused imx390_resume(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct v4l2_subdev *sd = i2c_get_clientdata(client); struct imx390 *imx390 = to_imx390(sd); - const struct imx390_reg_list *reg_list; - int ret; - - reg_list = &imx390->cur_mode->reg_list; - ret = imx390_write_reg_list(imx390, reg_list); - if (ret) { - dev_err(&client->dev, "resume: failed to apply cur mode"); - return ret; - } mutex_lock(&imx390->mutex); - if (imx390->streaming) { - ret = imx390_start_streaming(imx390); - if (ret) { - imx390->streaming = false; - imx390_stop_streaming(imx390); - mutex_unlock(&imx390->mutex); - return ret; - } - } - + imx390->pre_mode = NULL; mutex_unlock(&imx390->mutex); return 0; diff --git a/drivers/media/i2c/isx031.c b/drivers/media/i2c/isx031.c index a84d33e1c1ef..661db1fa4a31 100644 --- a/drivers/media/i2c/isx031.c +++ b/drivers/media/i2c/isx031.c @@ -377,26 +377,9 @@ static int __maybe_unused isx031_resume(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct v4l2_subdev *sd = i2c_get_clientdata(client); struct isx031 *isx031 = to_isx031(sd); - const struct isx031_reg_list *reg_list; - int ret; - reg_list = &isx031->cur_mode->reg_list; - ret = isx031_write_reg_list(isx031, reg_list); - if (ret) { - dev_err(&client->dev, "resume: failed to apply cur mode"); - return ret; - } mutex_lock(&isx031->mutex); - if (isx031->streaming) { - ret = isx031_start_streaming(isx031); - if (ret) { - isx031->streaming = false; - isx031_stop_streaming(isx031); - mutex_unlock(&isx031->mutex); - return ret; - } - } - + isx031->pre_mode = NULL; mutex_unlock(&isx031->mutex); return 0; diff --git a/drivers/media/i2c/ti960-des.c b/drivers/media/i2c/ti960-des.c index 380d000822c6..57ef7b93a471 100644 --- a/drivers/media/i2c/ti960-des.c +++ b/drivers/media/i2c/ti960-des.c @@ -1818,6 +1818,21 @@ static void ti960_remove(struct i2c_client *client) #ifdef CONFIG_PM static int ti960_suspend(struct device *dev) { + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *subdev = i2c_get_clientdata(client); + struct ti960 *va = to_ti960(subdev); + int i; + for (i = 0; i < NR_OF_TI960_SINK_PADS; i++) { + if (va->sub_devs[i].serializer) { + i2c_unregister_device(va->sub_devs[i].serializer); + va->sub_devs[i].serializer = NULL; + } + + if (va->sub_devs[i].gpio_exp) { + i2c_unregister_device(va->sub_devs[i].gpio_exp); + va->sub_devs[i].gpio_exp = NULL; + } + } return 0; } From 9c56f2eadb17099bc0da7345d500773a9dce5d98 Mon Sep 17 00:00:00 2001 From: jiabinhe Date: Thu, 7 Nov 2024 16:27:23 +0800 Subject: [PATCH 2/2] driver: fix s3 issue patch 2 Signed-off-by: jiabinhe --- drivers/media/i2c/imx390.c | 71 ++++++--- drivers/media/i2c/isx031.c | 82 ++++++++--- drivers/media/i2c/ti960-des.c | 178 ++++++++++++++++------- drivers/media/i2c/ti960-reg.h | 8 +- drivers/media/pci/intel/ipu-isys-video.c | 2 + include/media/ti960.h | 3 + 6 files changed, 243 insertions(+), 101 deletions(-) diff --git a/drivers/media/i2c/imx390.c b/drivers/media/i2c/imx390.c index 97b60993b361..14aa3d94147f 100644 --- a/drivers/media/i2c/imx390.c +++ b/drivers/media/i2c/imx390.c @@ -1149,6 +1149,29 @@ static int imx390_write_reg_list(struct imx390 *imx390, return 0; } +static int imx390_identify_module(struct imx390 *imx390) +{ + struct i2c_client *client = v4l2_get_subdevdata(&imx390->sd); + int ret; + int retry = 50; + u32 val; + + while (retry--) { + ret = imx390_read_reg(imx390, IMX390_REG_CHIP_ID, + IMX390_REG_VALUE_16BIT, &val); + if (ret == 0) + break; + usleep_range(100000, 100500); + } + + if (ret) + return ret; + + dev_info(&client->dev, "chip id: %04x", val); + + return 0; +} + static int imx390_is_hdr(struct imx390 *imx390) { // int mode_ix = self->s_data->sensor_mode_id; @@ -1681,9 +1704,32 @@ static int __maybe_unused imx390_resume(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct v4l2_subdev *sd = i2c_get_clientdata(client); struct imx390 *imx390 = to_imx390(sd); + const struct imx390_reg_list *reg_list; + int ret; + ret = imx390_identify_module(imx390); + if (ret == 0) { + reg_list = &imx390->cur_mode->reg_list; + ret = imx390_write_reg_list(imx390, reg_list); + if (ret) { + dev_err(&client->dev, "resume: failed to apply cur mode"); + return ret; + } + } else { + dev_err(&client->dev, "imx390 resume failed"); + return ret; + } mutex_lock(&imx390->mutex); - imx390->pre_mode = NULL; + if (imx390->streaming) { + ret = imx390_start_streaming(imx390); + if (ret) { + imx390->streaming = false; + imx390_stop_streaming(imx390); + mutex_unlock(&imx390->mutex); + return ret; + } + } + mutex_unlock(&imx390->mutex); return 0; @@ -1876,29 +1922,6 @@ static const struct v4l2_subdev_internal_ops imx390_internal_ops = { .open = imx390_open, }; -static int imx390_identify_module(struct imx390 *imx390) -{ - struct i2c_client *client = v4l2_get_subdevdata(&imx390->sd); - int ret; - int retry = 50; - u32 val; - - while (retry--) { - ret = imx390_read_reg(imx390, IMX390_REG_CHIP_ID, - IMX390_REG_VALUE_16BIT, &val); - if (ret == 0) - break; - usleep_range(10000, 10500); - } - - if (ret) - return ret; - - dev_info(&client->dev, "chip id: %04x", val); - - return 0; -} - static void imx390_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); diff --git a/drivers/media/i2c/isx031.c b/drivers/media/i2c/isx031.c index 661db1fa4a31..a39206593f15 100644 --- a/drivers/media/i2c/isx031.c +++ b/drivers/media/i2c/isx031.c @@ -88,6 +88,14 @@ static const struct isx031_reg isx031_init_reg[] = { {ISX031_REG_LEN_08BIT, 0x0172, 0x00}, // close R_EBD {ISX031_REG_LEN_08BIT, 0x8A01, 0x00}, // mode transition to start-up state {ISX031_REG_LEN_DELAY, 0x0000, 0x64}, // delay 100 ms + /* External sync */ + {ISX031_REG_LEN_08BIT, 0xBF14, 0x01}, /* SG_MODE_APL */ + {ISX031_REG_LEN_08BIT, 0x8AFF, 0x0c}, /* Hi-Z (input setting or output disabled) */ + {ISX031_REG_LEN_08BIT, 0x0153, 0x00}, + {ISX031_REG_LEN_08BIT, 0x8AF0, 0x01}, /* external pulse-based sync */ + {ISX031_REG_LEN_08BIT, 0x0144, 0x00}, + {ISX031_REG_LEN_08BIT, 0x8AF1, 0x00}, + }; static const struct isx031_reg isx031_1920_1536_30fps_reg[] = { @@ -132,6 +140,7 @@ static const struct isx031_reg isx031_1920_1080_30fps_reg[] = { {ISX031_REG_LEN_08BIT, 0xBF0B, 0x04}, {ISX031_REG_LEN_08BIT, 0xBF0C, 0xE4}, {ISX031_REG_LEN_08BIT, 0xBF0D, 0x00}, + }; static const struct isx031_reg isx031_1280_720_30fps_reg[] = { @@ -273,6 +282,34 @@ static int isx031_write_reg_list(struct isx031 *isx031, return 0; } +static int isx031_identify_module(struct isx031 *isx031) +{ + struct i2c_client *client = isx031->client; + int ret; + int retry = 50; + u32 val; + + while (retry--) { + ret = isx031_read_reg(isx031, ISX031_REG_CHIP_ID, + ISX031_REG_LEN_08BIT, &val); + if (ret == 0) + break; + usleep_range(100000, 100500); + } + + if (ret) + return ret; + + /* chip id not known yet */ + if (val != ISX031_CHIP_ID) { + dev_err(&client->dev, "read chip id: %x != %x", + val, ISX031_CHIP_ID); + return -ENXIO; + } + + return isx031_write_reg_list(isx031, &isx031_init_reg_list); +} + static void isx031_update_pad_format(const struct isx031_mode *mode, struct v4l2_mbus_framefmt *fmt) { @@ -377,9 +414,32 @@ static int __maybe_unused isx031_resume(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct v4l2_subdev *sd = i2c_get_clientdata(client); struct isx031 *isx031 = to_isx031(sd); + const struct isx031_reg_list *reg_list; + int ret; + ret = isx031_identify_module(isx031); + if (ret == 0) { + reg_list = &isx031->cur_mode->reg_list; + ret = isx031_write_reg_list(isx031, reg_list); + if (ret) { + dev_err(&client->dev, "resume: failed to apply cur mode"); + return ret; + } + } else { + dev_err(&client->dev, "isx031 resume failed"); + return ret; + } mutex_lock(&isx031->mutex); - isx031->pre_mode = NULL; + if (isx031->streaming) { + ret = isx031_start_streaming(isx031); + if (ret) { + isx031->streaming = false; + isx031_stop_streaming(isx031); + mutex_unlock(&isx031->mutex); + return ret; + } + } + mutex_unlock(&isx031->mutex); return 0; @@ -479,26 +539,6 @@ static const struct v4l2_subdev_internal_ops isx031_internal_ops = { .open = isx031_open, }; -static int isx031_identify_module(struct isx031 *isx031) -{ - struct i2c_client *client = isx031->client; - int ret; - u32 val; - - ret = isx031_read_reg(isx031, ISX031_REG_CHIP_ID, - ISX031_REG_LEN_08BIT, &val); - if (ret) - return ret; - /* chip id not known yet */ - if (val != ISX031_CHIP_ID) { - dev_err(&client->dev, "read chip id: %x != %x", - val, ISX031_CHIP_ID); - return -ENXIO; - } - - return isx031_write_reg_list(isx031, &isx031_init_reg_list); -} - static void isx031_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); diff --git a/drivers/media/i2c/ti960-des.c b/drivers/media/i2c/ti960-des.c index 57ef7b93a471..a06813da0946 100644 --- a/drivers/media/i2c/ti960-des.c +++ b/drivers/media/i2c/ti960-des.c @@ -31,6 +31,7 @@ #define MIPI_CSI2_TYPE_RAW12 0x2c #define MIPI_CSI2_TYPE_YUV422_8 0x1e +#define SUFFIX_BASE 96 struct ti960_slave { unsigned short addr; @@ -146,50 +147,56 @@ static struct regmap_config ti960_reg_config16 = { .reg_format_endian = REGMAP_ENDIAN_BIG, }; -static s64 ti960_query_sub_stream[NR_OF_TI960_SINK_PADS] = { - 0, 0, 0, 0 +static s64 ti960_query_sub_stream[NR_OF_TI960_DEVS][NR_OF_TI960_SINK_PADS] = { + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, }; -static void set_sub_stream_fmt(int index, u32 code) +static void set_sub_stream_fmt(int port, int index, u32 code) { - ti960_query_sub_stream[index] &= 0xFFFFFFFFFFFF0000; - ti960_query_sub_stream[index] |= code; + ti960_query_sub_stream[port][index] &= 0xFFFFFFFFFFFF0000; + ti960_query_sub_stream[port][index] |= code; } -static void set_sub_stream_h(int index, u32 height) +static void set_sub_stream_h(int port, int index, u32 height) { s64 val = height & 0xFFFF; - ti960_query_sub_stream[index] &= 0xFFFFFFFF0000FFFF; - ti960_query_sub_stream[index] |= val << 16; + ti960_query_sub_stream[port][index] &= 0xFFFFFFFF0000FFFF; + ti960_query_sub_stream[port][index] |= val << 16; } -static void set_sub_stream_w(int index, u32 width) +static void set_sub_stream_w(int port, int index, u32 width) { s64 val = width & 0xFFFF; - ti960_query_sub_stream[index] &= 0xFFFF0000FFFFFFFF; - ti960_query_sub_stream[index] |= val << 32; + ti960_query_sub_stream[port][index] &= 0xFFFF0000FFFFFFFF; + ti960_query_sub_stream[port][index] |= val << 32; } -static void set_sub_stream_dt(int index, u32 dt) +static void set_sub_stream_dt(int port, int index, u32 dt) { s64 val = dt & 0xFF; - ti960_query_sub_stream[index] &= 0xFF00FFFFFFFFFFFF; - ti960_query_sub_stream[index] |= val << 48; + ti960_query_sub_stream[port][index] &= 0xFF00FFFFFFFFFFFF; + ti960_query_sub_stream[port][index] |= val << 48; } -static void set_sub_stream_vc_id(int index, u32 vc_id) +static void set_sub_stream_vc_id(int port, int index, u32 vc_id) { s64 val = vc_id & 0xFF; - ti960_query_sub_stream[index] &= 0x00FFFFFFFFFFFFFF; - ti960_query_sub_stream[index] |= val << 56; + ti960_query_sub_stream[port][index] &= 0x00FFFFFFFFFFFFFF; + ti960_query_sub_stream[port][index] |= val << 56; } -static u8 ti960_set_sub_stream[] = { - 0, 0, 0, 0 +static u8 ti960_set_sub_stream[NR_OF_TI960_DEVS][NR_OF_TI960_SINK_PADS] = { + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, }; static int bus_switch(struct ti960 *va) @@ -558,6 +565,7 @@ static int ti960_set_format(struct v4l2_subdev *subdev, struct ti960 *va = to_ti960(subdev); const struct ti960_csi_data_format *csi_format; struct v4l2_mbus_framefmt *ffmt; + u8 port = va->pdata->suffix - SUFFIX_BASE; csi_format = ti960_validate_csi_data_format( fmt->format.code); @@ -577,17 +585,17 @@ static int ti960_set_format(struct v4l2_subdev *subdev, fmt->format = *ffmt; if (fmt->pad < NR_OF_TI960_SINK_PADS) { - set_sub_stream_fmt(fmt->pad, ffmt->code); - set_sub_stream_h(fmt->pad, ffmt->height); - set_sub_stream_w(fmt->pad, ffmt->width); + set_sub_stream_fmt(port, fmt->pad, ffmt->code); + set_sub_stream_h(port, fmt->pad, ffmt->height); + set_sub_stream_w(port, fmt->pad, ffmt->width); /* select correct csi-2 data type id */ if (ffmt->code >= MEDIA_BUS_FMT_UYVY8_1X16 && ffmt->code <= MEDIA_BUS_FMT_YVYU8_1X16) - set_sub_stream_dt(fmt->pad, MIPI_CSI2_TYPE_YUV422_8); + set_sub_stream_dt(port, fmt->pad, MIPI_CSI2_TYPE_YUV422_8); else - set_sub_stream_dt(fmt->pad, MIPI_CSI2_TYPE_RAW12); - set_sub_stream_vc_id(fmt->pad, fmt->pad); + set_sub_stream_dt(port, fmt->pad, MIPI_CSI2_TYPE_RAW12); + set_sub_stream_vc_id(port, fmt->pad, fmt->pad); dev_dbg(subdev->dev, "framefmt: width: %d, height: %d, code: 0x%x.\n", ffmt->width, ffmt->height, ffmt->code); @@ -842,9 +850,8 @@ static int ti960_registered(struct v4l2_subdev *subdev) { struct ti960 *va = to_ti960(subdev); struct i2c_client *client = v4l2_get_subdevdata(subdev); - int i, j, k, l, m, rval; + int i, j, k, l, rval; bool port_registered[NR_OF_TI960_SINK_PADS]; - unsigned char val; for (i = 0 ; i < NR_OF_TI960_SINK_PADS; i++) port_registered[i] = false; @@ -1006,6 +1013,7 @@ static bool ti960_broadcast_mode(struct v4l2_subdev *subdev) unsigned int h = 0, w = 0, code = 0; bool single_stream = true; int i, rval; + u8 port = va->pdata->suffix - SUFFIX_BASE; for (i = 0; i < NR_OF_TI960_SINK_PADS; i++) { struct media_pad *remote_pad = @@ -1014,7 +1022,7 @@ static bool ti960_broadcast_mode(struct v4l2_subdev *subdev) if (!remote_pad) continue; - if (!ti960_set_sub_stream[i]) + if (!ti960_set_sub_stream[port][i]) continue; sd = media_entity_to_v4l2_subdev(remote_pad->entity); @@ -1126,7 +1134,8 @@ static int ti960_set_frame_sync(struct ti960 *va, int enable) return rval; } } - + dev_info(va->sd.dev, "Succeed to %s frame sync\n", + enable ? "enable" : "disable"); return 0; } @@ -1139,6 +1148,8 @@ static int ti960_set_stream(struct v4l2_subdev *subdev, int enable) unsigned short rx_port; unsigned short ser_alias; int sd_idx = -1; + u8 port = va->pdata->suffix - SUFFIX_BASE; + DECLARE_BITMAP(rx_port_enabled, 32); dev_dbg(va->sd.dev, "TI960 set stream, enable %d\n", enable); @@ -1156,7 +1167,7 @@ static int ti960_set_stream(struct v4l2_subdev *subdev, int enable) if (!remote_pad) continue; - if (!ti960_set_sub_stream[i]) + if (!ti960_set_sub_stream[port][i]) continue; /* Find ti960 subdev */ @@ -1314,6 +1325,14 @@ static int ti960_set_stream_vc(struct ti960 *va, u8 vc_id, u8 state) i, state); return rval; } + + rval = ti960_fsin_gpio_init(va, &va->sub_devs[i]); + if (rval) { + dev_err(va->sd.dev, + "Failed to enable frame sync gpio init.\n"); + return rval; + } + if (va->subdev_pdata[i].module_flags & TI960_FL_RESET) { rval = reset_sensor(va, &va->sub_devs[i], &va->subdev_pdata[i]); if (rval) @@ -1336,16 +1355,16 @@ static const struct v4l2_subdev_core_ops ti960_core_subdev_ops = { .s_power = ti960_set_power, }; -static u8 ti960_get_nubmer_of_streaming(void) +static u8 ti960_get_nubmer_of_streaming(struct ti960 *va, u8 port) { u8 n = 0; u8 i = 0; - + mutex_lock(&va->mutex); for (; i < ARRAY_SIZE(ti960_set_sub_stream); i++) { - if (ti960_set_sub_stream[i]) + if (ti960_set_sub_stream[port][i]) n++; } - + mutex_unlock(&va->mutex); return n; } @@ -1356,6 +1375,7 @@ static int ti960_s_ctrl(struct v4l2_ctrl *ctrl) u32 val; u8 vc_id; u8 state; + u8 port = va->pdata->suffix - SUFFIX_BASE; switch (ctrl->id) { case V4L2_CID_IPU_SET_SUB_STREAM: @@ -1371,12 +1391,12 @@ static int ti960_s_ctrl(struct v4l2_ctrl *ctrl) ti960_reg_write(va, TI960_CSI_PORT_SEL, 0x01); ti960_reg_read(va, TI960_CSI_CTL, &val); if (state) { - if (ti960_get_nubmer_of_streaming() == 0) + if (ti960_get_nubmer_of_streaming(va, port) == 0) val |= TI960_CSI_CONTS_CLOCK; - ti960_set_sub_stream[vc_id] = state; + ti960_set_sub_stream[port][vc_id] = state; } else { - ti960_set_sub_stream[vc_id] = state; - if (ti960_get_nubmer_of_streaming() == 0) + ti960_set_sub_stream[port][vc_id] = state; + if (ti960_get_nubmer_of_streaming(va, port) == 0) val &= ~TI960_CSI_CONTS_CLOCK; } @@ -1394,7 +1414,7 @@ static const struct v4l2_ctrl_ops ti960_ctrl_ops = { .s_ctrl = ti960_s_ctrl, }; -static const struct v4l2_ctrl_config ti960_controls[] = { +static const struct v4l2_ctrl_config ti960_basic_controls[3] = { { .ops = &ti960_ctrl_ops, .id = V4L2_CID_LINK_FREQ, @@ -1416,27 +1436,64 @@ static const struct v4l2_ctrl_config ti960_controls[] = { .step = 1, .def = 0, }, + { + .ops = &ti960_ctrl_ops, + .id = V4L2_CID_IPU_SET_SUB_STREAM, + .name = "set virtual channel", + .type = V4L2_CTRL_TYPE_INTEGER64, + .max = 0xFFFF, + .min = 0, + .def = 0, + .step = 1, + }, +}; + +static const struct v4l2_ctrl_config ti960_query_sub_control[NR_OF_TI960_DEVS] = { { .ops = &ti960_ctrl_ops, .id = V4L2_CID_IPU_QUERY_SUB_STREAM, .name = "query virtual channel", .type = V4L2_CTRL_TYPE_INTEGER_MENU, - .max = ARRAY_SIZE(ti960_query_sub_stream) - 1, + .max = ARRAY_SIZE(ti960_query_sub_stream[0]) - 1, .min = 0, .def = 0, .menu_skip_mask = 0, - .qmenu_int = ti960_query_sub_stream, + .qmenu_int = ti960_query_sub_stream[0], }, { .ops = &ti960_ctrl_ops, - .id = V4L2_CID_IPU_SET_SUB_STREAM, - .name = "set virtual channel", - .type = V4L2_CTRL_TYPE_INTEGER64, - .max = 0xFFFF, + .id = V4L2_CID_IPU_QUERY_SUB_STREAM, + .name = "query virtual channel", + .type = V4L2_CTRL_TYPE_INTEGER_MENU, + .max = ARRAY_SIZE(ti960_query_sub_stream[1]) - 1, .min = 0, .def = 0, - .step = 1, + .menu_skip_mask = 0, + .qmenu_int = ti960_query_sub_stream[1], + }, + { + .ops = &ti960_ctrl_ops, + .id = V4L2_CID_IPU_QUERY_SUB_STREAM, + .name = "query virtual channel", + .type = V4L2_CTRL_TYPE_INTEGER_MENU, + .max = ARRAY_SIZE(ti960_query_sub_stream[2]) - 1, + .min = 0, + .def = 0, + .menu_skip_mask = 0, + .qmenu_int = ti960_query_sub_stream[2], + }, + { + .ops = &ti960_ctrl_ops, + .id = V4L2_CID_IPU_QUERY_SUB_STREAM, + .name = "query virtual channel", + .type = V4L2_CTRL_TYPE_INTEGER_MENU, + .max = ARRAY_SIZE(ti960_query_sub_stream[3]) - 1, + .min = 0, + .def = 0, + .menu_skip_mask = 0, + .qmenu_int = ti960_query_sub_stream[3], }, + }; static const struct v4l2_subdev_pad_ops ti960_sd_pad_ops = { @@ -1456,7 +1513,8 @@ static int ti960_register_subdev(struct ti960 *va) { int i, rval; struct i2c_client *client = v4l2_get_subdevdata(&va->sd); - + u8 port = va->pdata->suffix - SUFFIX_BASE; + u8 ctrl_num = ARRAY_SIZE(ti960_basic_controls) + 1; v4l2_subdev_init(&va->sd, &ti960_sd_ops); snprintf(va->sd.name, sizeof(va->sd.name), "TI960 %c", va->pdata->suffix); @@ -1468,8 +1526,7 @@ static int ti960_register_subdev(struct ti960 *va) v4l2_set_subdevdata(&va->sd, client); - v4l2_ctrl_handler_init(&va->ctrl_handler, - ARRAY_SIZE(ti960_controls)); + v4l2_ctrl_handler_init(&va->ctrl_handler, ctrl_num); if (va->ctrl_handler.error) { dev_err(va->sd.dev, @@ -1480,9 +1537,9 @@ static int ti960_register_subdev(struct ti960 *va) va->sd.ctrl_handler = &va->ctrl_handler; - for (i = 0; i < ARRAY_SIZE(ti960_controls); i++) { + for (i = 0; i < ARRAY_SIZE(ti960_basic_controls); i++) { const struct v4l2_ctrl_config *cfg = - &ti960_controls[i]; + &ti960_basic_controls[i]; struct v4l2_ctrl *ctrl; ctrl = v4l2_ctrl_new_custom(&va->ctrl_handler, cfg, NULL); @@ -1494,6 +1551,18 @@ static int ti960_register_subdev(struct ti960 *va) } } + const struct v4l2_ctrl_config *cfg = + &ti960_query_sub_control[port]; + struct v4l2_ctrl *ctrl; + + ctrl = v4l2_ctrl_new_custom(&va->ctrl_handler, cfg, NULL); + if (!ctrl) { + dev_err(va->sd.dev, + "Failed to create ctrl %s!\n", cfg->name); + rval = va->ctrl_handler.error; + goto failed_out; + } + va->link_freq = v4l2_ctrl_find(&va->ctrl_handler, V4L2_CID_LINK_FREQ); switch (va->pdata->link_freq_mbps) { case 1600: @@ -1591,6 +1660,10 @@ static int ti960_init(struct ti960 *va) if (rval) return rval; + rval = ti960_set_frame_sync(va, 1); + if (rval) + dev_err(va->sd.dev, + "Failed to write TI960 sync setting\n"); return 0; } @@ -1822,6 +1895,7 @@ static int ti960_suspend(struct device *dev) struct v4l2_subdev *subdev = i2c_get_clientdata(client); struct ti960 *va = to_ti960(subdev); int i; + for (i = 0; i < NR_OF_TI960_SINK_PADS; i++) { if (va->sub_devs[i].serializer) { i2c_unregister_device(va->sub_devs[i].serializer); @@ -1833,6 +1907,7 @@ static int ti960_suspend(struct device *dev) va->sub_devs[i].gpio_exp = NULL; } } + return 0; } @@ -1844,7 +1919,6 @@ static int ti960_resume(struct device *dev) int i, rval; struct ti960_subdev *sensor_subdev; struct ti960_subdev_pdata *pdata; - unsigned char val; rval = ti960_init(va); if (rval) { diff --git a/drivers/media/i2c/ti960-reg.h b/drivers/media/i2c/ti960-reg.h index 5330c81799d8..32351fe87101 100644 --- a/drivers/media/i2c/ti960-reg.h +++ b/drivers/media/i2c/ti960-reg.h @@ -23,10 +23,10 @@ static const struct ti960_register_write ti960_frame_sync_settings[2][5] = { {0x1c, 0x00}, }, { - {0x19, 0x15}, /* Frame sync high time.*/ - {0x1a, 0xb3}, - {0x1b, 0xc3}, /* Frame sync low time. */ - {0x1c, 0x4f}, + {0x19, 0x0a}, /* Frame sync high time.*/ + {0x1a, 0xd7}, + {0x1b, 0xce}, /* Frame sync low time. */ + {0x1c, 0xac}, {0x18, 0x01}, /* Enable frame sync. and use high/low mode */ } }; diff --git a/drivers/media/pci/intel/ipu-isys-video.c b/drivers/media/pci/intel/ipu-isys-video.c index b32459a5a211..5c3b0a1db79a 100644 --- a/drivers/media/pci/intel/ipu-isys-video.c +++ b/drivers/media/pci/intel/ipu-isys-video.c @@ -1022,6 +1022,7 @@ static void media_pipeline_stop_for_vc(struct ipu_isys_video *av) dev_dbg(av->vdev.entity.graph_obj.mdev->dev, "stream count: %u, av entity name: %s.\n", av->ip.csi2->stream_count, av->vdev.entity.name); + mutex_lock(&mdev->graph_mutex); while ((entity = media_graph_walk_next(&graph))) { dev_dbg(av->vdev.entity.graph_obj.mdev->dev, "walk entity name: %s.\n", @@ -1029,6 +1030,7 @@ static void media_pipeline_stop_for_vc(struct ipu_isys_video *av) if (av->ip.csi2->stream_count == 0 || !strcmp(entity->name, av->vdev.entity.name)) entity->pads[0].pipe = NULL; } + mutex_unlock(&mdev->graph_mutex); media_graph_walk_cleanup(&graph); } diff --git a/include/media/ti960.h b/include/media/ti960.h index b9aa89cbf6ed..f174b767817b 100644 --- a/include/media/ti960.h +++ b/include/media/ti960.h @@ -20,6 +20,9 @@ #define PIXEL_ORDER_BGGR 2 #define PIXEL_ORDER_GBRG 3 +#define NR_OF_TI960_DEVS 4 +#define NR_OF_TI960_CTRLS 4 + #define NR_OF_TI960_VCS_PER_SINK_PAD 2 #define NR_OF_TI960_VCS_SOURCE_PAD 4 #define NR_OF_TI960_SOURCE_PADS 1