diff --git a/drivers/media/i2c/hi846.c b/drivers/media/i2c/hi846.c index 8e9fc572106be6cac410bbfefc2e7bd959d059c7..827cb1c6ecd9c8e4beee5cd7b8d43d6bcb8671b3 100644 --- a/drivers/media/i2c/hi846.c +++ b/drivers/media/i2c/hi846.c @@ -590,11 +590,47 @@ static int hi846_init_controls(struct hi846 *hi846) return 0; } +static int hi846_set_video_mode(struct hi846 *hi846, int fps) +{ + int frame_length; + int ret; + int dummy_lines; + + frame_length = hi846->cur_mode->link_freq / fps / HI846_LINE_LENGTH; + dummy_lines = (frame_length > hi846->cur_mode->frame_len) ? + (frame_length - hi846->cur_mode->frame_len) : 0; + + frame_length = hi846->cur_mode->frame_len + dummy_lines; + + pr_debug("%s: frame length calculated: %d\n", __func__, frame_length); + + ret = hi846_write_reg_16(hi846, HI846_REG_FLL, frame_length & 0xFFFF); + ret = hi846_write_reg_16(hi846, HI846_REG_LLP, HI846_LINE_LENGTH & 0xFFFF); + + return ret; +} + static int hi846_start_streaming(struct hi846 *hi846) { struct i2c_client *client = v4l2_get_subdevdata(&hi846->sd); int ret; + mutex_lock(&hi846->mutex); + + ret = hi846_write_reg_list(hi846, &hi846_init_regs_list); + if (ret) { + dev_err(&client->dev, "failed to set plls: %d\n", ret); + return ret; + } + + ret = hi846_write_reg_list(hi846, &hi846->cur_mode->reg_list); + if (ret) { + dev_err(&client->dev, "failed to set mode: %d\n", ret); + return ret; + } + + hi846_set_video_mode(hi846, hi846->cur_mode->fps); + ret = __v4l2_ctrl_handler_setup(hi846->sd.ctrl_handler); if (ret) return ret; @@ -606,7 +642,6 @@ static int hi846_start_streaming(struct hi846 *hi846) dev_err(&client->dev, "failed to start stream"); return ret; } - mdelay(10); #endif #if 0 @@ -615,9 +650,12 @@ static int hi846_start_streaming(struct hi846 *hi846) dev_err(&client->dev, "failed to set test pattern: %d\n", ret); return ret; } - mdelay(10); #endif + hi846->streaming = 1; + + mutex_unlock(&hi846->mutex); + dev_dbg(&client->dev, "%s: STARTED\n", __func__); return 0; @@ -629,8 +667,14 @@ static void hi846_stop_streaming(struct hi846 *hi846) dev_dbg(&client->dev, "%s\n", __func__); + mutex_lock(&hi846->mutex); + if (hi846_write_reg(hi846, HI846_REG_MODE_SELECT, HI846_MODE_STANDBY)) dev_err(&client->dev, "failed to stop stream"); + + hi846->streaming = 0; + + mutex_unlock(&hi846->mutex); } static int hi846_set_stream(struct v4l2_subdev *sd, int enable) @@ -644,7 +688,6 @@ static int hi846_set_stream(struct v4l2_subdev *sd, int enable) if (hi846->streaming == enable) return 0; - mutex_lock(&hi846->mutex); if (enable) { ret = pm_runtime_get_sync(&client->dev); if (ret < 0) { @@ -666,9 +709,6 @@ static int hi846_set_stream(struct v4l2_subdev *sd, int enable) pm_runtime_put_autosuspend(&client->dev); } - hi846->streaming = enable; - mutex_unlock(&hi846->mutex); - return ret; } @@ -691,16 +731,20 @@ static int __maybe_unused hi846_suspend(struct device *dev) dev_dbg(dev, "%s\n", __func__); - //mutex_lock(&hi846->mutex); + mutex_lock(&hi846->mutex); if (hi846->streaming) hi846_stop_streaming(hi846); + mutex_unlock(&hi846->mutex); + if (!IS_ERR(hi846->clock)) clk_disable_unprepare(hi846->clock); - regulator_disable(hi846->vdd1_regulator); - regulator_disable(hi846->vdd_regulator); - //mutex_unlock(&hi846->mutex); + if (regulator_is_enabled(hi846->vdd1_regulator)) + regulator_disable(hi846->vdd1_regulator); + + if (regulator_is_enabled(hi846->vdd_regulator)) + regulator_disable(hi846->vdd_regulator); return 0; } @@ -717,6 +761,7 @@ static int __maybe_unused hi846_resume(struct device *dev) ret = hi846_regulator_enable(hi846); if (ret) { dev_err(dev, "enable regulator failed\n"); + mutex_unlock(&hi846->mutex); return ret; } @@ -726,7 +771,6 @@ static int __maybe_unused hi846_resume(struct device *dev) msleep(100); - //mutex_lock(&hi846->mutex); if (hi846->streaming) { ret = hi846_start_streaming(hi846); if (ret) { @@ -735,19 +779,18 @@ static int __maybe_unused hi846_resume(struct device *dev) } } - //mutex_unlock(&hi846->mutex); - return 0; error: hi846_stop_streaming(hi846); dev_err(dev, "%s: stopped streaming\n", __func__); hi846->streaming = 0; - //mutex_unlock(&hi846->mutex); error_regulator: regulator_disable(hi846->vdd1_regulator); - regulator_disable(hi846->vdd_regulator); + if (regulator_is_enabled(hi846->vdd_regulator)) + regulator_disable(hi846->vdd_regulator); + return ret; } @@ -788,26 +831,6 @@ static int hi846_get_frame_interval(struct v4l2_subdev *sd, return 0; } -static int hi846_set_video_mode(struct hi846 *hi846, int fps) -{ - int frame_length; - int ret; - int dummy_lines; - - frame_length = hi846->cur_mode->link_freq / fps / HI846_LINE_LENGTH; - dummy_lines = (frame_length > hi846->cur_mode->frame_len) ? - (frame_length - hi846->cur_mode->frame_len) : 0; - - frame_length = hi846->cur_mode->frame_len + dummy_lines; - - pr_debug("%s: frame length calculated: %d\n", __func__, frame_length); - - ret = hi846_write_reg_16(hi846, HI846_REG_FLL, frame_length & 0xFFFF); - ret = hi846_write_reg_16(hi846, HI846_REG_LLP, HI846_LINE_LENGTH & 0xFFFF); - - return ret; -} - static int hi846_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *format) @@ -818,7 +841,6 @@ static int hi846_set_format(struct v4l2_subdev *sd, struct hi846_datafmt *fmt = hi846_find_datafmt(mf->code); int capturemode; u32 tgt_fps; - int ret; s32 vblank_def, h_blank; dev_dbg(&client->dev, "------------ starting %s ---------\n", __func__); @@ -855,29 +877,6 @@ static int hi846_set_format(struct v4l2_subdev *sd, mf->code = HI846_MEDIA_BUS_FORMAT; mf->field = V4L2_FIELD_NONE; - ret = pm_runtime_get_sync(&client->dev); - if (ret < 0) { - dev_err(&client->dev, "%s: pm_runtime_get failed: %d\n", - __func__, ret); - pm_runtime_put_noidle(&client->dev); - return ret; - } - - dev_dbg(&client->dev, "writing regs now\n"); - ret = hi846_write_reg_list(hi846, &hi846_init_regs_list); - if (ret) { - dev_err(&client->dev, "failed to set plls: %d\n", ret); - return ret; - } - - ret = hi846_write_reg_list(hi846, &hi846->cur_mode->reg_list); - if (ret) { - dev_err(&client->dev, "failed to set mode: %d\n", ret); - return ret; - } - - hi846_set_video_mode(hi846, tgt_fps); - hi846->streamcap.capturemode = capturemode; hi846->pix.width = mf->width; hi846->pix.height = mf->height; @@ -903,9 +902,6 @@ static int hi846_set_format(struct v4l2_subdev *sd, mf->width, mf->height, capturemode, fmt->code, fmt->colorspace); - pm_runtime_mark_last_busy(&client->dev); - pm_runtime_put_autosuspend(&client->dev); - dev_dbg(&client->dev, "--------------------------------------------\n"); return 0; } @@ -921,6 +917,13 @@ static int hi846_get_format(struct v4l2_subdev *sd, if (format->pad) return -EINVAL; + if (format->which == V4L2_SUBDEV_FORMAT_TRY) { + format->format = *v4l2_subdev_get_try_format(&hi846->sd, + cfg, + format->pad); + return 0; + } + dev_dbg(&client->dev, "hi846: starting %s\n", __func__); mutex_lock(&hi846->mutex); @@ -941,15 +944,10 @@ static int hi846_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code) { - pr_debug("%s: starting. pad: %d code index: %d (only 0 exists)\n", - __func__, code->pad, code->index); - if (code->pad || code->index >= ARRAY_SIZE(hi846_colour_fmts)) { - pr_debug("%s: error: code pad set or index too high\n", __func__); + if (code->pad || code->index > 0) return -EINVAL; - } - code->code = hi846_colour_fmts[code->index].code; - pr_debug("%s: code: 0x%x\n", __func__, code->code); + code->code = HI846_MEDIA_BUS_FORMAT; return 0; } @@ -962,7 +960,7 @@ static int hi846_enum_frame_size(struct v4l2_subdev *sd, dev_dbg(&client->dev, "%s frame size index: %d\n", __func__, fse->index); - if (fse->index >= ARRAY_SIZE(supported_modes)) + if (fse->pad || fse->index >= ARRAY_SIZE(supported_modes)) return -EINVAL; if (fse->code != HI846_MEDIA_BUS_FORMAT) { @@ -971,9 +969,9 @@ static int hi846_enum_frame_size(struct v4l2_subdev *sd, } fse->min_width = supported_modes[fse->index].width; - fse->max_width = fse->min_width; + fse->max_width = supported_modes[fse->index].width; fse->min_height = supported_modes[fse->index].height; - fse->max_height = fse->min_height; + fse->max_height = supported_modes[fse->index].height; dev_dbg(&client->dev, "%s: max width: %d max height: %d\n", __func__, fse->max_width, fse->max_height); @@ -990,11 +988,12 @@ static int hi846_enum_frame_intervals(struct v4l2_subdev *sd, dev_dbg(dev, "starting %s index %d\n", __func__, fie->index); - if (fie->index >= ARRAY_SIZE(supported_modes)) + if (fie->pad || fie->index >= ARRAY_SIZE(supported_modes)) return -EINVAL; fie->interval.numerator = 1; fie->interval.denominator = supported_modes[fie->index].fps; + dev_dbg(dev, "%s: index: %d: %d / %d\n", __func__, fie->index, fie->interval.numerator, fie->interval.denominator); @@ -1030,6 +1029,10 @@ static const struct v4l2_subdev_ops hi846_subdev_ops = { .pad = &hi846_pad_ops, }; +static const struct media_entity_operations hi846_subdev_entity_ops = { + .link_validate = v4l2_subdev_link_validate, +}; + static void hi846_gpio_assert(struct hi846 *hi846, int id, bool on) { struct hi846_gpio *gpio = &hi846->gpios[id]; @@ -1135,13 +1138,15 @@ static int hi846_remove(struct i2c_client *client) struct hi846 *hi846 = to_hi846(sd); v4l2_async_unregister_subdev(sd); + media_entity_cleanup(&sd->entity); v4l2_ctrl_handler_free(sd->ctrl_handler); pm_runtime_disable(&client->dev); pm_runtime_set_suspended(&client->dev); pm_runtime_put_noidle(&client->dev); mutex_destroy(&hi846->mutex); regulator_disable(hi846->vdd1_regulator); - regulator_disable(hi846->vdd_regulator); + if (regulator_is_enabled(hi846->vdd_regulator)) + regulator_disable(hi846->vdd_regulator); return 0; } @@ -1220,7 +1225,15 @@ static int hi846_probe(struct i2c_client *client) goto probe_error_v4l2_ctrl_handler_free; } + hi846->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + hi846->sd.entity.ops = &hi846_subdev_entity_ops; + hi846->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; hi846->pad.flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(&hi846->sd.entity, 1, &hi846->pad); + if (ret) { + dev_err(&client->dev, "failed to init entity pads: %d", ret); + goto probe_error_v4l2_ctrl_handler_free; + } ret = v4l2_async_register_subdev_sensor_common(&hi846->sd); if (ret < 0) { @@ -1238,6 +1251,7 @@ static int hi846_probe(struct i2c_client *client) return 0; probe_error_media_entity_cleanup: + media_entity_cleanup(&hi846->sd.entity); probe_error_v4l2_ctrl_handler_free: v4l2_ctrl_handler_free(hi846->sd.ctrl_handler); @@ -1245,7 +1259,8 @@ static int hi846_probe(struct i2c_client *client) probe_error_regulator: regulator_disable(hi846->vdd1_regulator); - regulator_disable(hi846->vdd_regulator); + if (regulator_is_enabled(hi846->vdd_regulator)) + regulator_disable(hi846->vdd_regulator); return ret; } diff --git a/drivers/media/i2c/s5k3l6xx.c b/drivers/media/i2c/s5k3l6xx.c index 52a19acf5cd0274fa47ba975abe70e27dfcb2678..ad5b97c3a98e815f2b8b6745852312a3d4f47780 100644 --- a/drivers/media/i2c/s5k3l6xx.c +++ b/drivers/media/i2c/s5k3l6xx.c @@ -229,16 +229,6 @@ module_param(debug, int, 0644); #define REG_ARR_CCM(n) (0x2800 + 36 * (n)) -static const char * const s5k5baf_supply_names[] = { - "vddio", /* I/O power supply 1.8V (1.65V to 1.95V) - or 2.8V (2.5V to 3.1V) */ - "vdda", /* Analog power supply 2.8V (2.6V to 3.0V) */ - "vddreg", /* Regulator input power supply 1.8V (1.7V to 1.9V) - or 2.8V (2.6V to 3.0) */ -}; -#define S5K5BAF_NUM_SUPPLIES 1 -// #define S5K5BAF_NUM_SUPPLIES ARRAY_SIZE(s5k5baf_supply_names) - struct s5k3l6_reg { u16 address; u16 val; @@ -521,7 +511,7 @@ struct s5k5baf { struct s5k5baf_gpio gpios[NUM_GPIOS]; enum v4l2_mbus_type bus_type; u8 nlanes; - struct regulator_bulk_data supplies[S5K5BAF_NUM_SUPPLIES]; + struct regulator *supply; struct clk *clock; u32 mclk_frequency; @@ -831,7 +821,7 @@ static int s5k5baf_power_on(struct s5k5baf *state) { int ret; - ret = regulator_bulk_enable(S5K5BAF_NUM_SUPPLIES, state->supplies); + ret = regulator_enable(state->supply); if (ret < 0) goto err; @@ -851,7 +841,8 @@ static int s5k5baf_power_on(struct s5k5baf *state) return 0; err_reg_dis: - regulator_bulk_disable(S5K5BAF_NUM_SUPPLIES, state->supplies); + if (regulator_is_enabled(state->supply)) + regulator_disable(state->supply); err: v4l2_err(&state->sd, "%s() failed (%d)\n", __func__, ret); return ret; @@ -870,8 +861,10 @@ static int s5k5baf_power_off(struct s5k5baf *state) if (!IS_ERR(state->clock)) clk_disable_unprepare(state->clock); - ret = regulator_bulk_disable(S5K5BAF_NUM_SUPPLIES, - state->supplies); + if (!regulator_is_enabled(state->supply)) + return 0; + + ret = regulator_disable(state->supply); if (ret < 0) v4l2_err(&state->sd, "failed to disable regulators\n"); else @@ -1560,17 +1553,12 @@ static int s5k5baf_configure_subdevs(struct s5k5baf *state, static int s5k5baf_configure_regulators(struct s5k5baf *state) { struct i2c_client *c = v4l2_get_subdevdata(&state->sd); - int ret; - int i; - for (i = 0; i < S5K5BAF_NUM_SUPPLIES; i++) - state->supplies[i].supply = s5k5baf_supply_names[i]; - - ret = devm_regulator_bulk_get(&c->dev, S5K5BAF_NUM_SUPPLIES, - state->supplies); - if (ret < 0) + state->supply = devm_regulator_get(&c->dev, "vddio"); + if (IS_ERR(state->supply)) v4l2_err(c, "failed to get regulators\n"); - return ret; + + return 0; } static int s5k5baf_probe(struct i2c_client *c) diff --git a/drivers/media/platform/imx8/mxc-mipi-csi2_yav.c b/drivers/media/platform/imx8/mxc-mipi-csi2_yav.c index e986f1890897b36b6fbbc118bfe8ecb82074f3ed..af0d74c370900e43c402dcbe3e73e919e3e98a05 100644 --- a/drivers/media/platform/imx8/mxc-mipi-csi2_yav.c +++ b/drivers/media/platform/imx8/mxc-mipi-csi2_yav.c @@ -371,10 +371,17 @@ static int mipi_csi2_s_stream(struct v4l2_subdev *sd, int enable) } v4l2_subdev_call(sensor_sd, video, s_stream, true); csi2dev->running++; + dev_dbg(&csi2dev->pdev->dev, "%s: running set to %d\n", __func__, + csi2dev->running); } else { + if (!csi2dev->running) + return ret; + v4l2_subdev_call(sensor_sd, video, s_stream, false); csi2dev->running--; + dev_dbg(&csi2dev->pdev->dev, "%s: running set to %d\n", __func__, + csi2dev->running); if (!csi2dev->running) { pm_runtime_put(dev); mxc_mipi_csi2_disable(csi2dev);