From 61bc6fbc44d07ac3677eab711ae35ca9e18301a7 Mon Sep 17 00:00:00 2001 From: "changhuang.liang" Date: Fri, 30 Sep 2022 15:19:26 +0800 Subject: [PATCH] sc2235: Use runtime/system pm Use runtime/system pm save power. Signed-off-by: changhuang.liang --- .../media/platform/starfive/v4l2_driver/sc2235.c | 104 ++++++++++++--------- 1 file changed, 62 insertions(+), 42 deletions(-) diff --git a/drivers/media/platform/starfive/v4l2_driver/sc2235.c b/drivers/media/platform/starfive/v4l2_driver/sc2235.c index e50de3a6..ae33487 100644 --- a/drivers/media/platform/starfive/v4l2_driver/sc2235.c +++ b/drivers/media/platform/starfive/v4l2_driver/sc2235.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -145,8 +146,6 @@ struct sc2235_dev { /* lock to protect all members below */ struct mutex lock; - int power_count; - struct v4l2_mbus_framefmt fmt; bool pending_fmt_change; @@ -956,9 +955,11 @@ static void sc2235_reset(struct sc2235_dev *sensor) usleep_range(20000, 25000); } -static int sc2235_set_power_on(struct sc2235_dev *sensor) +static int sc2235_set_power_on(struct device *dev) { - struct i2c_client *client = sensor->i2c_client; + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct sc2235_dev *sensor = to_sc2235_dev(sd); int ret; ret = clk_prepare_enable(sensor->xclk); @@ -986,12 +987,17 @@ xclk_off: return ret; } -static void sc2235_set_power_off(struct sc2235_dev *sensor) +static int sc2235_set_power_off(struct device *dev) { - sc2235_power(sensor, false); + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct sc2235_dev *sensor = to_sc2235_dev(sd); + sc2235_power(sensor, false); regulator_bulk_disable(SC2235_NUM_SUPPLIES, sensor->supplies); clk_disable_unprepare(sensor->xclk); + + return 0; } static int sc2235_set_power_dvp(struct sc2235_dev *sensor, bool on) @@ -1030,9 +1036,7 @@ static int sc2235_set_power(struct sc2235_dev *sensor, bool on) int ret = 0; if (on) { - ret = sc2235_set_power_on(sensor); - if (ret) - return ret; + pm_runtime_get_sync(&sensor->i2c_client->dev); ret = sc2235_restore_mode(sensor); if (ret) @@ -1045,12 +1049,12 @@ static int sc2235_set_power(struct sc2235_dev *sensor, bool on) goto power_off; if (!on) - sc2235_set_power_off(sensor); + pm_runtime_put_sync(&sensor->i2c_client->dev); return 0; power_off: - sc2235_set_power_off(sensor); + pm_runtime_put_sync(&sensor->i2c_client->dev); return ret; } @@ -1062,27 +1066,15 @@ static int sc2235_s_power(struct v4l2_subdev *sd, int on) mutex_lock(&sensor->lock); - /* - * If the power count is modified from 0 to != 0 or from != 0 to 0, - * update the power state. - */ - if (sensor->power_count == !on) { - ret = sc2235_set_power(sensor, !!on); - if (ret) - goto out; - } + ret = sc2235_set_power(sensor, !!on); + if (ret) + goto out; - /* Update the power count. */ - sensor->power_count += on ? 1 : -1; - WARN_ON(sensor->power_count < 0); -out: mutex_unlock(&sensor->lock); + return 0; - if (on && !ret && sensor->power_count == 1) { - /* restore controls */ - ret = v4l2_ctrl_handler_setup(&sensor->ctrls.handler); - } - +out: + mutex_unlock(&sensor->lock); return ret; } @@ -1377,6 +1369,9 @@ static int sc2235_g_volatile_ctrl(struct v4l2_ctrl *ctrl) /* v4l2_ctrl_lock() locks our own mutex */ + if (!pm_runtime_get_if_in_use(&sensor->i2c_client->dev)) + return 0; + switch (ctrl->id) { case V4L2_CID_AUTOGAIN: val = sc2235_get_gain(sensor); @@ -1392,6 +1387,8 @@ static int sc2235_g_volatile_ctrl(struct v4l2_ctrl *ctrl) break; } + pm_runtime_put(&sensor->i2c_client->dev); + return 0; } @@ -1406,9 +1403,9 @@ static int sc2235_s_ctrl(struct v4l2_ctrl *ctrl) /* * If the device is not powered up by the host driver do * not apply any controls to H/W at this time. Instead - * the controls will be restored right after power-up. + * the controls will be restored at start streaming time. */ - if (sensor->power_count == 0) + if (!pm_runtime_get_if_in_use(&sensor->i2c_client->dev)) return 0; switch (ctrl->id) { @@ -1447,6 +1444,8 @@ static int sc2235_s_ctrl(struct v4l2_ctrl *ctrl) break; } + pm_runtime_put(&sensor->i2c_client->dev); + return ret; } @@ -1678,6 +1677,12 @@ static int sc2235_s_stream(struct v4l2_subdev *sd, int enable) struct sc2235_dev *sensor = to_sc2235_dev(sd); int ret = 0; + if (enable) { + ret = v4l2_ctrl_handler_setup(&sensor->ctrls.handler); + if (ret) + return ret; + } + mutex_lock(&sensor->lock); if (sensor->streaming == !enable) { @@ -1756,28 +1761,22 @@ static int sc2235_check_chip_id(struct sc2235_dev *sensor) int ret = 0; u16 chip_id; - ret = sc2235_set_power_on(sensor); - if (ret) - return ret; - ret = sc2235_read_reg16(sensor, SC2235_REG_CHIP_ID, &chip_id); if (ret) { dev_err(&client->dev, "%s: failed to read chip identifier\n", __func__); - goto power_off; + return ret; } if (chip_id != SC2235_CHIP_ID) { dev_err(&client->dev, "%s: wrong chip identifier, expected 0x%x, got 0x%x\n", __func__, SC2235_CHIP_ID, chip_id); - ret = -ENXIO; + return -ENXIO; } dev_err(&client->dev, "%s: chip identifier, got 0x%x\n", __func__, chip_id); -power_off: - sc2235_set_power_off(sensor); - return ret; + return 0; } static int sc2235_probe(struct i2c_client *client) @@ -1890,22 +1889,33 @@ static int sc2235_probe(struct i2c_client *client) return ret; mutex_init(&sensor->lock); + ret = sc2235_set_power_on(dev); + if (ret) { + dev_err(dev, "failed to power on\n"); + goto entity_cleanup; + } + ret = sc2235_check_chip_id(sensor); if (ret) - goto entity_cleanup; + goto entity_power_off; ret = sc2235_init_controls(sensor); if (ret) - goto entity_cleanup; + goto entity_power_off; ret = v4l2_async_register_subdev_sensor(&sensor->sd); if (ret) goto free_ctrls; + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + return 0; free_ctrls: v4l2_ctrl_handler_free(&sensor->ctrls.handler); +entity_power_off: + sc2235_set_power_off(dev); entity_cleanup: media_entity_cleanup(&sensor->sd.entity); mutex_destroy(&sensor->lock); @@ -1922,6 +1932,11 @@ static int sc2235_remove(struct i2c_client *client) v4l2_ctrl_handler_free(&sensor->ctrls.handler); mutex_destroy(&sensor->lock); + pm_runtime_disable(&client->dev); + if (!pm_runtime_status_suspended(&client->dev)) + sc2235_set_power_off(&client->dev); + pm_runtime_set_suspended(&client->dev); + return 0; } @@ -1937,10 +1952,15 @@ static const struct of_device_id sc2235_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, sc2235_dt_ids); +static const struct dev_pm_ops sc2235_pm_ops = { + SET_RUNTIME_PM_OPS(sc2235_set_power_off, sc2235_set_power_on, NULL) +}; + static struct i2c_driver sc2235_i2c_driver = { .driver = { .name = "sc2235", .of_match_table = sc2235_dt_ids, + .pm = &sc2235_pm_ops, }, .id_table = sc2235_id, .probe_new = sc2235_probe, -- 2.7.4