diff options
Diffstat (limited to 'drivers/media/i2c/hi556.c')
-rw-r--r-- | drivers/media/i2c/hi556.c | 92 |
1 files changed, 42 insertions, 50 deletions
diff --git a/drivers/media/i2c/hi556.c b/drivers/media/i2c/hi556.c index 076c19fcf99c..de573cee4451 100644 --- a/drivers/media/i2c/hi556.c +++ b/drivers/media/i2c/hi556.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2019 Intel Corporation. -#include <linux/unaligned.h> #include <linux/acpi.h> #include <linux/clk.h> #include <linux/delay.h> @@ -10,6 +9,8 @@ #include <linux/module.h> #include <linux/pm_runtime.h> #include <linux/regulator/consumer.h> +#include <linux/unaligned.h> + #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-fwnode.h> @@ -631,6 +632,8 @@ static const char * const hi556_supply_names[] = { }; struct hi556 { + struct device *dev; + struct v4l2_subdev sd; struct media_pad pad; struct v4l2_ctrl_handler ctrl_handler; @@ -715,7 +718,6 @@ static int hi556_write_reg(struct hi556 *hi556, u16 reg, u16 len, u32 val) static int hi556_write_reg_list(struct hi556 *hi556, const struct hi556_reg_list *r_list) { - struct i2c_client *client = v4l2_get_subdevdata(&hi556->sd); unsigned int i; int ret; @@ -724,7 +726,7 @@ static int hi556_write_reg_list(struct hi556 *hi556, HI556_REG_VALUE_16BIT, r_list->regs[i].val); if (ret) { - dev_err_ratelimited(&client->dev, + dev_err_ratelimited(hi556->dev, "failed to write reg 0x%4.4x. error = %d\n", r_list->regs[i].address, ret); return ret; @@ -785,7 +787,6 @@ static int hi556_set_ctrl(struct v4l2_ctrl *ctrl) { struct hi556 *hi556 = container_of(ctrl->handler, struct hi556, ctrl_handler); - struct i2c_client *client = v4l2_get_subdevdata(&hi556->sd); s64 exposure_max; int ret = 0; @@ -801,7 +802,7 @@ static int hi556_set_ctrl(struct v4l2_ctrl *ctrl) } /* V4L2 controls values will be applied only when power is already up */ - if (!pm_runtime_get_if_in_use(&client->dev)) + if (!pm_runtime_get_if_in_use(hi556->dev)) return 0; switch (ctrl->id) { @@ -835,7 +836,7 @@ static int hi556_set_ctrl(struct v4l2_ctrl *ctrl) break; } - pm_runtime_put(&client->dev); + pm_runtime_put(hi556->dev); return ret; } @@ -921,7 +922,6 @@ static void hi556_assign_pad_format(const struct hi556_mode *mode, static int hi556_identify_module(struct hi556 *hi556) { - struct i2c_client *client = v4l2_get_subdevdata(&hi556->sd); int ret; u32 val; @@ -934,7 +934,7 @@ static int hi556_identify_module(struct hi556 *hi556) return ret; if (val != HI556_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x!=%x\n", + dev_err(hi556->dev, "chip id mismatch: %x!=%x\n", HI556_CHIP_ID, val); return -ENXIO; } @@ -998,7 +998,6 @@ static int hi556_get_selection(struct v4l2_subdev *sd, static int hi556_start_streaming(struct hi556 *hi556) { - struct i2c_client *client = v4l2_get_subdevdata(&hi556->sd); const struct hi556_reg_list *reg_list; int link_freq_index, ret; @@ -1010,14 +1009,14 @@ static int hi556_start_streaming(struct hi556 *hi556) reg_list = &link_freq_configs[link_freq_index].reg_list; ret = hi556_write_reg_list(hi556, reg_list); if (ret) { - dev_err(&client->dev, "failed to set plls\n"); + dev_err(hi556->dev, "failed to set plls\n"); return ret; } reg_list = &hi556->cur_mode->reg_list; ret = hi556_write_reg_list(hi556, reg_list); if (ret) { - dev_err(&client->dev, "failed to set mode\n"); + dev_err(hi556->dev, "failed to set mode\n"); return ret; } @@ -1029,7 +1028,7 @@ static int hi556_start_streaming(struct hi556 *hi556) HI556_REG_VALUE_16BIT, HI556_MODE_STREAMING); if (ret) { - dev_err(&client->dev, "failed to set stream\n"); + dev_err(hi556->dev, "failed to set stream\n"); return ret; } @@ -1038,22 +1037,19 @@ static int hi556_start_streaming(struct hi556 *hi556) static void hi556_stop_streaming(struct hi556 *hi556) { - struct i2c_client *client = v4l2_get_subdevdata(&hi556->sd); - if (hi556_write_reg(hi556, HI556_REG_MODE_SELECT, HI556_REG_VALUE_16BIT, HI556_MODE_STANDBY)) - dev_err(&client->dev, "failed to set stream\n"); + dev_err(hi556->dev, "failed to set stream\n"); } static int hi556_set_stream(struct v4l2_subdev *sd, int enable) { struct hi556 *hi556 = to_hi556(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = 0; mutex_lock(&hi556->mutex); if (enable) { - ret = pm_runtime_resume_and_get(&client->dev); + ret = pm_runtime_resume_and_get(hi556->dev); if (ret < 0) { mutex_unlock(&hi556->mutex); return ret; @@ -1062,11 +1058,11 @@ static int hi556_set_stream(struct v4l2_subdev *sd, int enable) ret = hi556_start_streaming(hi556); if (ret) { hi556_stop_streaming(hi556); - pm_runtime_put(&client->dev); + pm_runtime_put(hi556->dev); } } else { hi556_stop_streaming(hi556); - pm_runtime_put(&client->dev); + pm_runtime_put(hi556->dev); } mutex_unlock(&hi556->mutex); @@ -1217,7 +1213,6 @@ static int hi556_check_hwcfg(struct device *dev) struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = V4L2_MBUS_CSI2_DPHY }; - u32 mclk; int ret = 0; unsigned int i, j; @@ -1235,18 +1230,6 @@ static int hi556_check_hwcfg(struct device *dev) if (ret) return dev_err_probe(dev, ret, "parsing endpoint failed\n"); - ret = fwnode_property_read_u32(fwnode, "clock-frequency", &mclk); - if (ret) { - dev_err(dev, "can't get clock frequency\n"); - goto check_hwcfg_error; - } - - if (mclk != HI556_MCLK) { - dev_err(dev, "external clock %d is not supported\n", mclk); - ret = -EINVAL; - goto check_hwcfg_error; - } - if (bus_cfg.bus.mipi_csi2.num_data_lanes != 2) { dev_err(dev, "number of CSI2 data lanes %d is not supported\n", bus_cfg.bus.mipi_csi2.num_data_lanes); @@ -1289,7 +1272,7 @@ static void hi556_remove(struct i2c_client *client) v4l2_async_unregister_subdev(sd); media_entity_cleanup(&sd->entity); v4l2_ctrl_handler_free(sd->ctrl_handler); - pm_runtime_disable(&client->dev); + pm_runtime_disable(hi556->dev); mutex_destroy(&hi556->mutex); } @@ -1336,6 +1319,7 @@ static int hi556_resume(struct device *dev) static int hi556_probe(struct i2c_client *client) { struct hi556 *hi556; + unsigned long freq; bool full_power; int i, ret; @@ -1347,40 +1331,48 @@ static int hi556_probe(struct i2c_client *client) if (!hi556) return -ENOMEM; + hi556->dev = &client->dev; + v4l2_i2c_subdev_init(&hi556->sd, client, &hi556_subdev_ops); - hi556->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", + hi556->reset_gpio = devm_gpiod_get_optional(hi556->dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(hi556->reset_gpio)) - return dev_err_probe(&client->dev, PTR_ERR(hi556->reset_gpio), + return dev_err_probe(hi556->dev, PTR_ERR(hi556->reset_gpio), "failed to get reset GPIO\n"); - hi556->clk = devm_clk_get_optional(&client->dev, "clk"); + hi556->clk = devm_v4l2_sensor_clk_get(hi556->dev, "clk"); if (IS_ERR(hi556->clk)) - return dev_err_probe(&client->dev, PTR_ERR(hi556->clk), + return dev_err_probe(hi556->dev, PTR_ERR(hi556->clk), "failed to get clock\n"); + freq = clk_get_rate(hi556->clk); + if (freq != HI556_MCLK) + return dev_err_probe(hi556->dev, -EINVAL, + "external clock %lu is not supported\n", + freq); + for (i = 0; i < ARRAY_SIZE(hi556_supply_names); i++) hi556->supplies[i].supply = hi556_supply_names[i]; - ret = devm_regulator_bulk_get(&client->dev, + ret = devm_regulator_bulk_get(hi556->dev, ARRAY_SIZE(hi556_supply_names), hi556->supplies); if (ret) - return dev_err_probe(&client->dev, ret, + return dev_err_probe(hi556->dev, ret, "failed to get regulators\n"); - full_power = acpi_dev_state_d0(&client->dev); + full_power = acpi_dev_state_d0(hi556->dev); if (full_power) { /* Ensure non ACPI managed resources are enabled */ - ret = hi556_resume(&client->dev); + ret = hi556_resume(hi556->dev); if (ret) - return dev_err_probe(&client->dev, ret, + return dev_err_probe(hi556->dev, ret, "failed to power on sensor\n"); ret = hi556_identify_module(hi556); if (ret) { - dev_err(&client->dev, "failed to find sensor: %d\n", ret); + dev_err(hi556->dev, "failed to find sensor: %d\n", ret); goto probe_error_power_off; } } @@ -1389,7 +1381,7 @@ static int hi556_probe(struct i2c_client *client) hi556->cur_mode = &supported_modes[0]; ret = hi556_init_controls(hi556); if (ret) { - dev_err(&client->dev, "failed to init controls: %d\n", ret); + dev_err(hi556->dev, "failed to init controls: %d\n", ret); goto probe_error_v4l2_ctrl_handler_free; } @@ -1400,22 +1392,22 @@ static int hi556_probe(struct i2c_client *client) hi556->pad.flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_pads_init(&hi556->sd.entity, 1, &hi556->pad); if (ret) { - dev_err(&client->dev, "failed to init entity pads: %d\n", ret); + dev_err(hi556->dev, "failed to init entity pads: %d\n", ret); goto probe_error_v4l2_ctrl_handler_free; } ret = v4l2_async_register_subdev_sensor(&hi556->sd); if (ret < 0) { - dev_err(&client->dev, "failed to register V4L2 subdev: %d\n", + dev_err(hi556->dev, "failed to register V4L2 subdev: %d\n", ret); goto probe_error_media_entity_cleanup; } /* Set the device's state to active if it's in D0 state. */ if (full_power) - pm_runtime_set_active(&client->dev); - pm_runtime_enable(&client->dev); - pm_runtime_idle(&client->dev); + pm_runtime_set_active(hi556->dev); + pm_runtime_enable(hi556->dev); + pm_runtime_idle(hi556->dev); return 0; @@ -1428,7 +1420,7 @@ probe_error_v4l2_ctrl_handler_free: probe_error_power_off: if (full_power) - hi556_suspend(&client->dev); + hi556_suspend(hi556->dev); return ret; } |