summaryrefslogtreecommitdiff
path: root/drivers/media/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/i2c')
-rw-r--r--drivers/media/i2c/Kconfig12
-rw-r--r--drivers/media/i2c/Makefile1
-rw-r--r--drivers/media/i2c/adv7511-v4l2.c22
-rw-r--r--drivers/media/i2c/adv7604.c18
-rw-r--r--drivers/media/i2c/adv7842.c10
-rw-r--r--drivers/media/i2c/ccs/ccs-core.c12
-rw-r--r--drivers/media/i2c/cx25840/cx25840-ir.c20
-rw-r--r--drivers/media/i2c/dw9768.c6
-rw-r--r--drivers/media/i2c/hi556.c70
-rw-r--r--drivers/media/i2c/hi846.c18
-rw-r--r--drivers/media/i2c/imx208.c82
-rw-r--r--drivers/media/i2c/imx274.c102
-rw-r--r--drivers/media/i2c/imx290.c2
-rw-r--r--drivers/media/i2c/imx319.c2
-rw-r--r--drivers/media/i2c/imx355.c2
-rw-r--r--drivers/media/i2c/max9286.c7
-rw-r--r--drivers/media/i2c/ov13858.c2
-rw-r--r--drivers/media/i2c/ov2740.c69
-rw-r--r--drivers/media/i2c/ov5670.c80
-rw-r--r--drivers/media/i2c/ov5675.c71
-rw-r--r--drivers/media/i2c/ov5693.c1537
-rw-r--r--drivers/media/i2c/ov8856.c162
-rw-r--r--drivers/media/i2c/ov8865.c478
-rw-r--r--drivers/media/i2c/s5c73m3/s5c73m3-spi.c6
24 files changed, 2330 insertions, 461 deletions
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index d6a5d4ca439a..69c56e24a612 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -469,6 +469,7 @@ config VIDEO_VPX3220
config VIDEO_MAX9286
tristate "Maxim MAX9286 GMSL deserializer support"
depends on I2C && I2C_MUX
+ depends on VIDEO_V4L2
depends on OF_GPIO
select V4L2_FWNODE
select VIDEO_V4L2_SUBDEV_API
@@ -1058,6 +1059,17 @@ config VIDEO_OV5675
To compile this driver as a module, choose M here: the
module will be called ov5675.
+config VIDEO_OV5693
+ tristate "OmniVision OV5693 sensor support"
+ depends on I2C && VIDEO_V4L2
+ select V4L2_FWNODE
+ help
+ This is a Video4Linux2 sensor driver for the OmniVision
+ OV5693 camera.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ov5693.
+
config VIDEO_OV5695
tristate "OmniVision OV5695 sensor support"
depends on I2C && VIDEO_V4L2
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index 4d4fe08d7a6a..b01f6cd05ee8 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -75,6 +75,7 @@ obj-$(CONFIG_VIDEO_OV5647) += ov5647.o
obj-$(CONFIG_VIDEO_OV5648) += ov5648.o
obj-$(CONFIG_VIDEO_OV5670) += ov5670.o
obj-$(CONFIG_VIDEO_OV5675) += ov5675.o
+obj-$(CONFIG_VIDEO_OV5693) += ov5693.o
obj-$(CONFIG_VIDEO_OV5695) += ov5695.o
obj-$(CONFIG_VIDEO_OV6650) += ov6650.o
obj-$(CONFIG_VIDEO_OV7251) += ov7251.o
diff --git a/drivers/media/i2c/adv7511-v4l2.c b/drivers/media/i2c/adv7511-v4l2.c
index 41f4e749a859..8e13cae40ec5 100644
--- a/drivers/media/i2c/adv7511-v4l2.c
+++ b/drivers/media/i2c/adv7511-v4l2.c
@@ -270,28 +270,6 @@ static int adv7511_pktmem_rd(struct v4l2_subdev *sd, u8 reg)
return adv_smbus_read_byte_data(state->i2c_pktmem, reg);
}
-static int adv7511_pktmem_wr(struct v4l2_subdev *sd, u8 reg, u8 val)
-{
- struct adv7511_state *state = get_adv7511_state(sd);
- int ret;
- int i;
-
- for (i = 0; i < 3; i++) {
- ret = i2c_smbus_write_byte_data(state->i2c_pktmem, reg, val);
- if (ret == 0)
- return 0;
- }
- v4l2_err(sd, "%s: i2c write error\n", __func__);
- return ret;
-}
-
-/* To set specific bits in the register, a clear-mask is given (to be AND-ed),
- and then the value-mask (to be OR-ed). */
-static inline void adv7511_pktmem_wr_and_or(struct v4l2_subdev *sd, u8 reg, u8 clr_mask, u8 val_mask)
-{
- adv7511_pktmem_wr(sd, reg, (adv7511_pktmem_rd(sd, reg) & clr_mask) | val_mask);
-}
-
static inline bool adv7511_have_hotplug(struct v4l2_subdev *sd)
{
return adv7511_rd(sd, 0x42) & MASK_ADV7511_HPD_DETECT;
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 44768b59a6ff..a2fa408d2d9f 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -398,14 +398,14 @@ static inline int io_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask,
return io_write(sd, reg, (io_read(sd, reg) & ~mask) | val);
}
-static inline int avlink_read(struct v4l2_subdev *sd, u8 reg)
+static inline int __always_unused avlink_read(struct v4l2_subdev *sd, u8 reg)
{
struct adv76xx_state *state = to_state(sd);
return adv76xx_read_check(state, ADV7604_PAGE_AVLINK, reg);
}
-static inline int avlink_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+static inline int __always_unused avlink_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct adv76xx_state *state = to_state(sd);
@@ -439,14 +439,14 @@ static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg)
return adv76xx_read_check(state, ADV76XX_PAGE_INFOFRAME, reg);
}
-static inline int infoframe_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+static inline int __always_unused infoframe_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct adv76xx_state *state = to_state(sd);
return regmap_write(state->regmap[ADV76XX_PAGE_INFOFRAME], reg, val);
}
-static inline int afe_read(struct v4l2_subdev *sd, u8 reg)
+static inline int __always_unused afe_read(struct v4l2_subdev *sd, u8 reg)
{
struct adv76xx_state *state = to_state(sd);
@@ -479,14 +479,14 @@ static inline int rep_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8
return rep_write(sd, reg, (rep_read(sd, reg) & ~mask) | val);
}
-static inline int edid_read(struct v4l2_subdev *sd, u8 reg)
+static inline int __always_unused edid_read(struct v4l2_subdev *sd, u8 reg)
{
struct adv76xx_state *state = to_state(sd);
return adv76xx_read_check(state, ADV76XX_PAGE_EDID, reg);
}
-static inline int edid_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+static inline int __always_unused edid_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct adv76xx_state *state = to_state(sd);
@@ -570,7 +570,7 @@ static inline int hdmi_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8
return hdmi_write(sd, reg, (hdmi_read(sd, reg) & ~mask) | val);
}
-static inline int test_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+static inline int __always_unused test_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct adv76xx_state *state = to_state(sd);
@@ -601,14 +601,14 @@ static inline int cp_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 v
return cp_write(sd, reg, (cp_read(sd, reg) & ~mask) | val);
}
-static inline int vdp_read(struct v4l2_subdev *sd, u8 reg)
+static inline int __always_unused vdp_read(struct v4l2_subdev *sd, u8 reg)
{
struct adv76xx_state *state = to_state(sd);
return adv76xx_read_check(state, ADV7604_PAGE_VDP, reg);
}
-static inline int vdp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+static inline int __always_unused vdp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct adv76xx_state *state = to_state(sd);
diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
index 7f8acbdf0db4..9d6eed0f8281 100644
--- a/drivers/media/i2c/adv7842.c
+++ b/drivers/media/i2c/adv7842.c
@@ -256,21 +256,11 @@ static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
return &container_of(ctrl->handler, struct adv7842_state, hdl)->sd;
}
-static inline unsigned hblanking(const struct v4l2_bt_timings *t)
-{
- return V4L2_DV_BT_BLANKING_WIDTH(t);
-}
-
static inline unsigned htotal(const struct v4l2_bt_timings *t)
{
return V4L2_DV_BT_FRAME_WIDTH(t);
}
-static inline unsigned vblanking(const struct v4l2_bt_timings *t)
-{
- return V4L2_DV_BT_BLANKING_HEIGHT(t);
-}
-
static inline unsigned vtotal(const struct v4l2_bt_timings *t)
{
return V4L2_DV_BT_FRAME_HEIGHT(t);
diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c
index 5363f3bcafe3..9158d3ce45c0 100644
--- a/drivers/media/i2c/ccs/ccs-core.c
+++ b/drivers/media/i2c/ccs/ccs-core.c
@@ -2758,13 +2758,13 @@ ident_show(struct device *dev, struct device_attribute *attr, char *buf)
struct ccs_module_info *minfo = &sensor->minfo;
if (minfo->mipi_manufacturer_id)
- return snprintf(buf, PAGE_SIZE, "%4.4x%4.4x%2.2x\n",
- minfo->mipi_manufacturer_id, minfo->model_id,
- minfo->revision_number) + 1;
+ return sysfs_emit(buf, "%4.4x%4.4x%2.2x\n",
+ minfo->mipi_manufacturer_id, minfo->model_id,
+ minfo->revision_number) + 1;
else
- return snprintf(buf, PAGE_SIZE, "%2.2x%4.4x%2.2x\n",
- minfo->smia_manufacturer_id, minfo->model_id,
- minfo->revision_number) + 1;
+ return sysfs_emit(buf, "%2.2x%4.4x%2.2x\n",
+ minfo->smia_manufacturer_id, minfo->model_id,
+ minfo->revision_number) + 1;
}
static DEVICE_ATTR_RO(ident);
diff --git a/drivers/media/i2c/cx25840/cx25840-ir.c b/drivers/media/i2c/cx25840/cx25840-ir.c
index 2cf3e6a1f9e1..9d7d1d149f1a 100644
--- a/drivers/media/i2c/cx25840/cx25840-ir.c
+++ b/drivers/media/i2c/cx25840/cx25840-ir.c
@@ -136,19 +136,6 @@ static inline u16 count_to_clock_divider(unsigned int d)
return (u16) d;
}
-static inline u16 ns_to_clock_divider(unsigned int ns)
-{
- return count_to_clock_divider(
- DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ / 1000000 * ns, 1000));
-}
-
-static inline unsigned int clock_divider_to_ns(unsigned int divider)
-{
- /* Period of the Rx or Tx clock in ns */
- return DIV_ROUND_CLOSEST((divider + 1) * 1000,
- CX25840_IR_REFCLK_FREQ / 1000000);
-}
-
static inline u16 carrier_freq_to_clock_divider(unsigned int freq)
{
return count_to_clock_divider(
@@ -160,13 +147,6 @@ static inline unsigned int clock_divider_to_carrier_freq(unsigned int divider)
return DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ, (divider + 1) * 16);
}
-static inline u16 freq_to_clock_divider(unsigned int freq,
- unsigned int rollovers)
-{
- return count_to_clock_divider(
- DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ, freq * rollovers));
-}
-
static inline unsigned int clock_divider_to_freq(unsigned int divider,
unsigned int rollovers)
{
diff --git a/drivers/media/i2c/dw9768.c b/drivers/media/i2c/dw9768.c
index c086580efac7..65c6acf3ced9 100644
--- a/drivers/media/i2c/dw9768.c
+++ b/drivers/media/i2c/dw9768.c
@@ -469,6 +469,11 @@ static int dw9768_probe(struct i2c_client *client)
dw9768->sd.entity.function = MEDIA_ENT_F_LENS;
+ /*
+ * Device is already turned on by i2c-core with ACPI domain PM.
+ * Attempt to turn off the device to satisfy the privacy LED concerns.
+ */
+ pm_runtime_set_active(dev);
pm_runtime_enable(dev);
if (!pm_runtime_enabled(dev)) {
ret = dw9768_runtime_resume(dev);
@@ -483,6 +488,7 @@ static int dw9768_probe(struct i2c_client *client)
dev_err(dev, "failed to register V4L2 subdev: %d", ret);
goto err_power_off;
}
+ pm_runtime_idle(dev);
return 0;
diff --git a/drivers/media/i2c/hi556.c b/drivers/media/i2c/hi556.c
index 8db1cbedc1fd..055d1aa8410e 100644
--- a/drivers/media/i2c/hi556.c
+++ b/drivers/media/i2c/hi556.c
@@ -495,6 +495,9 @@ struct hi556 {
/* Streaming on/off */
bool streaming;
+
+ /* True if the device has been identified */
+ bool identified;
};
static u64 to_pixel_rate(u32 f_index)
@@ -757,12 +760,41 @@ static void hi556_assign_pad_format(const struct hi556_mode *mode,
fmt->field = V4L2_FIELD_NONE;
}
+static int hi556_identify_module(struct hi556 *hi556)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&hi556->sd);
+ int ret;
+ u32 val;
+
+ if (hi556->identified)
+ return 0;
+
+ ret = hi556_read_reg(hi556, HI556_REG_CHIP_ID,
+ HI556_REG_VALUE_16BIT, &val);
+ if (ret)
+ return ret;
+
+ if (val != HI556_CHIP_ID) {
+ dev_err(&client->dev, "chip id mismatch: %x!=%x",
+ HI556_CHIP_ID, val);
+ return -ENXIO;
+ }
+
+ hi556->identified = true;
+
+ return 0;
+}
+
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;
+ ret = hi556_identify_module(hi556);
+ if (ret)
+ return ret;
+
link_freq_index = hi556->cur_mode->link_freq_index;
reg_list = &link_freq_configs[link_freq_index].reg_list;
ret = hi556_write_reg_list(hi556, reg_list);
@@ -1001,26 +1033,6 @@ static const struct v4l2_subdev_internal_ops hi556_internal_ops = {
.open = hi556_open,
};
-static int hi556_identify_module(struct hi556 *hi556)
-{
- struct i2c_client *client = v4l2_get_subdevdata(&hi556->sd);
- int ret;
- u32 val;
-
- ret = hi556_read_reg(hi556, HI556_REG_CHIP_ID,
- HI556_REG_VALUE_16BIT, &val);
- if (ret)
- return ret;
-
- if (val != HI556_CHIP_ID) {
- dev_err(&client->dev, "chip id mismatch: %x!=%x",
- HI556_CHIP_ID, val);
- return -ENXIO;
- }
-
- return 0;
-}
-
static int hi556_check_hwcfg(struct device *dev)
{
struct fwnode_handle *ep;
@@ -1106,6 +1118,7 @@ static int hi556_remove(struct i2c_client *client)
static int hi556_probe(struct i2c_client *client)
{
struct hi556 *hi556;
+ bool full_power;
int ret;
ret = hi556_check_hwcfg(&client->dev);
@@ -1120,10 +1133,14 @@ static int hi556_probe(struct i2c_client *client)
return -ENOMEM;
v4l2_i2c_subdev_init(&hi556->sd, client, &hi556_subdev_ops);
- ret = hi556_identify_module(hi556);
- if (ret) {
- dev_err(&client->dev, "failed to find sensor: %d", ret);
- return ret;
+
+ full_power = acpi_dev_state_d0(&client->dev);
+ if (full_power) {
+ ret = hi556_identify_module(hi556);
+ if (ret) {
+ dev_err(&client->dev, "failed to find sensor: %d", ret);
+ return ret;
+ }
}
mutex_init(&hi556->mutex);
@@ -1152,7 +1169,9 @@ static int hi556_probe(struct i2c_client *client)
goto probe_error_media_entity_cleanup;
}
- pm_runtime_set_active(&client->dev);
+ /* 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);
@@ -1189,6 +1208,7 @@ static struct i2c_driver hi556_i2c_driver = {
},
.probe_new = hi556_probe,
.remove = hi556_remove,
+ .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
};
module_i2c_driver(hi556_i2c_driver);
diff --git a/drivers/media/i2c/hi846.c b/drivers/media/i2c/hi846.c
index 822ce3021fde..ad35c3ff3611 100644
--- a/drivers/media/i2c/hi846.c
+++ b/drivers/media/i2c/hi846.c
@@ -7,9 +7,9 @@
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/module.h>
-#include <linux/of_graph.h>
#include <linux/pm_runtime.h>
#include <linux/pm.h>
+#include <linux/property.h>
#include <linux/regulator/consumer.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
@@ -1656,7 +1656,7 @@ err_reg:
return ret;
}
-static void hi846_power_off(struct hi846 *hi846)
+static int hi846_power_off(struct hi846 *hi846)
{
if (hi846->rst_gpio)
gpiod_set_value_cansleep(hi846->rst_gpio, 1);
@@ -1665,7 +1665,7 @@ static void hi846_power_off(struct hi846 *hi846)
gpiod_set_value_cansleep(hi846->shutdown_gpio, 1);
clk_disable_unprepare(hi846->clock);
- regulator_bulk_disable(HI846_NUM_SUPPLIES, hi846->supplies);
+ return regulator_bulk_disable(HI846_NUM_SUPPLIES, hi846->supplies);
}
static int __maybe_unused hi846_suspend(struct device *dev)
@@ -1677,9 +1677,7 @@ static int __maybe_unused hi846_suspend(struct device *dev)
if (hi846->streaming)
hi846_stop_streaming(hi846);
- hi846_power_off(hi846);
-
- return 0;
+ return hi846_power_off(hi846);
}
static int __maybe_unused hi846_resume(struct device *dev)
@@ -2164,7 +2162,11 @@ static int hi846_remove(struct i2c_client *client)
return 0;
}
-static UNIVERSAL_DEV_PM_OPS(hi846_pm_ops, hi846_suspend, hi846_resume, NULL);
+static const struct dev_pm_ops hi846_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+ SET_RUNTIME_PM_OPS(hi846_suspend, hi846_resume, NULL)
+};
static const struct of_device_id hi846_of_match[] = {
{ .compatible = "hynix,hi846", },
@@ -2176,7 +2178,7 @@ static struct i2c_driver hi846_i2c_driver = {
.driver = {
.name = "hi846",
.pm = &hi846_pm_ops,
- .of_match_table = of_match_ptr(hi846_of_match),
+ .of_match_table = hi846_of_match,
},
.probe_new = hi846_probe,
.remove = hi846_remove,
diff --git a/drivers/media/i2c/imx208.c b/drivers/media/i2c/imx208.c
index 6f3d9c1b5879..b9516b2f1c15 100644
--- a/drivers/media/i2c/imx208.c
+++ b/drivers/media/i2c/imx208.c
@@ -296,6 +296,9 @@ struct imx208 {
/* OTP data */
bool otp_read;
char otp_data[IMX208_OTP_SIZE];
+
+ /* True if the device has been identified */
+ bool identified;
};
static inline struct imx208 *to_imx208(struct v4l2_subdev *_sd)
@@ -619,6 +622,34 @@ static int imx208_set_pad_format(struct v4l2_subdev *sd,
return 0;
}
+static int imx208_identify_module(struct imx208 *imx208)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);
+ int ret;
+ u32 val;
+
+ if (imx208->identified)
+ return 0;
+
+ ret = imx208_read_reg(imx208, IMX208_REG_CHIP_ID,
+ 2, &val);
+ if (ret) {
+ dev_err(&client->dev, "failed to read chip id %x\n",
+ IMX208_CHIP_ID);
+ return ret;
+ }
+
+ if (val != IMX208_CHIP_ID) {
+ dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
+ IMX208_CHIP_ID, val);
+ return -EIO;
+ }
+
+ imx208->identified = true;
+
+ return 0;
+}
+
/* Start streaming */
static int imx208_start_streaming(struct imx208 *imx208)
{
@@ -626,6 +657,10 @@ static int imx208_start_streaming(struct imx208 *imx208)
const struct imx208_reg_list *reg_list;
int ret, link_freq_index;
+ ret = imx208_identify_module(imx208);
+ if (ret)
+ return ret;
+
/* Setup PLL */
link_freq_index = imx208->cur_mode->link_freq_index;
reg_list = &link_freq_configs[link_freq_index].reg_list;
@@ -752,29 +787,6 @@ error:
}
/* Verify chip ID */
-static int imx208_identify_module(struct imx208 *imx208)
-{
- struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);
- int ret;
- u32 val;
-
- ret = imx208_read_reg(imx208, IMX208_REG_CHIP_ID,
- 2, &val);
- if (ret) {
- dev_err(&client->dev, "failed to read chip id %x\n",
- IMX208_CHIP_ID);
- return ret;
- }
-
- if (val != IMX208_CHIP_ID) {
- dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
- IMX208_CHIP_ID, val);
- return -EIO;
- }
-
- return 0;
-}
-
static const struct v4l2_subdev_video_ops imx208_video_ops = {
.s_stream = imx208_set_stream,
};
@@ -813,6 +825,10 @@ static int imx208_read_otp(struct imx208 *imx208)
goto out_unlock;
}
+ ret = imx208_identify_module(imx208);
+ if (ret)
+ goto out_pm_put;
+
/* Write register address */
msgs[0].addr = client->addr;
msgs[0].flags = 0;
@@ -831,6 +847,7 @@ static int imx208_read_otp(struct imx208 *imx208)
ret = 0;
}
+out_pm_put:
pm_runtime_put(&client->dev);
out_unlock:
@@ -961,6 +978,7 @@ static int imx208_probe(struct i2c_client *client)
{
struct imx208 *imx208;
int ret;
+ bool full_power;
u32 val = 0;
device_property_read_u32(&client->dev, "clock-frequency", &val);
@@ -978,11 +996,14 @@ static int imx208_probe(struct i2c_client *client)
/* Initialize subdev */
v4l2_i2c_subdev_init(&imx208->sd, client, &imx208_subdev_ops);
- /* Check module identity */
- ret = imx208_identify_module(imx208);
- if (ret) {
- dev_err(&client->dev, "failed to find sensor: %d", ret);
- goto error_probe;
+ full_power = acpi_dev_state_d0(&client->dev);
+ if (full_power) {
+ /* Check module identity */
+ ret = imx208_identify_module(imx208);
+ if (ret) {
+ dev_err(&client->dev, "failed to find sensor: %d", ret);
+ goto error_probe;
+ }
}
/* Set default mode to max resolution */
@@ -1017,7 +1038,9 @@ static int imx208_probe(struct i2c_client *client)
goto error_async_subdev;
}
- pm_runtime_set_active(&client->dev);
+ /* 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);
@@ -1077,6 +1100,7 @@ static struct i2c_driver imx208_i2c_driver = {
},
.probe_new = imx208_probe,
.remove = imx208_remove,
+ .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
};
module_i2c_driver(imx208_i2c_driver);
diff --git a/drivers/media/i2c/imx274.c b/drivers/media/i2c/imx274.c
index 0dce92872176..2aa15b9c23cc 100644
--- a/drivers/media/i2c/imx274.c
+++ b/drivers/media/i2c/imx274.c
@@ -27,6 +27,7 @@
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
+#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
/*
@@ -1367,6 +1368,10 @@ static int imx274_s_frame_interval(struct v4l2_subdev *sd,
int min, max, def;
int ret;
+ ret = pm_runtime_resume_and_get(&imx274->client->dev);
+ if (ret < 0)
+ return ret;
+
mutex_lock(&imx274->lock);
ret = imx274_set_frame_interval(imx274, fi->interval);
@@ -1398,6 +1403,7 @@ static int imx274_s_frame_interval(struct v4l2_subdev *sd,
unlock:
mutex_unlock(&imx274->lock);
+ pm_runtime_put(&imx274->client->dev);
return ret;
}
@@ -1457,7 +1463,7 @@ static int imx274_s_stream(struct v4l2_subdev *sd, int on)
goto fail;
/*
- * update frame rate & expsoure. if the last mode is different,
+ * update frame rate & exposure. if the last mode is different,
* HMAX could be changed. As the result, frame rate & exposure
* are changed.
* gain is not affected.
@@ -1494,7 +1500,7 @@ fail:
/*
* imx274_get_frame_length - Function for obtaining current frame length
* @priv: Pointer to device structure
- * @val: Pointer to obainted value
+ * @val: Pointer to obtained value
*
* frame_length = vmax x (svr + 1), in unit of hmax.
*
@@ -1904,7 +1910,21 @@ fail:
return err;
}
+static int imx274_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ if (code->index > 0)
+ return -EINVAL;
+
+ /* only supported format in the driver is Raw 10 bits SRGGB */
+ code->code = MEDIA_BUS_FMT_SRGGB10_1X10;
+
+ return 0;
+}
+
static const struct v4l2_subdev_pad_ops imx274_pad_ops = {
+ .enum_mbus_code = imx274_enum_mbus_code,
.get_fmt = imx274_get_fmt,
.set_fmt = imx274_set_fmt,
.get_selection = imx274_get_selection,
@@ -1938,27 +1958,66 @@ static const struct i2c_device_id imx274_id[] = {
};
MODULE_DEVICE_TABLE(i2c, imx274_id);
+static int imx274_fwnode_parse(struct device *dev)
+{
+ struct fwnode_handle *endpoint;
+ /* Only CSI2 is supported */
+ struct v4l2_fwnode_endpoint ep = {
+ .bus_type = V4L2_MBUS_CSI2_DPHY
+ };
+ int ret;
+
+ endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL);
+ if (!endpoint) {
+ dev_err(dev, "Endpoint node not found\n");
+ return -EINVAL;
+ }
+
+ ret = v4l2_fwnode_endpoint_parse(endpoint, &ep);
+ fwnode_handle_put(endpoint);
+ if (ret == -ENXIO) {
+ dev_err(dev, "Unsupported bus type, should be CSI2\n");
+ return ret;
+ } else if (ret) {
+ dev_err(dev, "Parsing endpoint node failed %d\n", ret);
+ return ret;
+ }
+
+ /* Check number of data lanes, only 4 lanes supported */
+ if (ep.bus.mipi_csi2.num_data_lanes != 4) {
+ dev_err(dev, "Invalid data lanes: %d\n",
+ ep.bus.mipi_csi2.num_data_lanes);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int imx274_probe(struct i2c_client *client)
{
struct v4l2_subdev *sd;
struct stimx274 *imx274;
+ struct device *dev = &client->dev;
int ret;
/* initialize imx274 */
- imx274 = devm_kzalloc(&client->dev, sizeof(*imx274), GFP_KERNEL);
+ imx274 = devm_kzalloc(dev, sizeof(*imx274), GFP_KERNEL);
if (!imx274)
return -ENOMEM;
mutex_init(&imx274->lock);
- imx274->inck = devm_clk_get_optional(&client->dev, "inck");
+ ret = imx274_fwnode_parse(dev);
+ if (ret)
+ return ret;
+
+ imx274->inck = devm_clk_get_optional(dev, "inck");
if (IS_ERR(imx274->inck))
return PTR_ERR(imx274->inck);
- ret = imx274_regulators_get(&client->dev, imx274);
+ ret = imx274_regulators_get(dev, imx274);
if (ret) {
- dev_err(&client->dev,
- "Failed to get power regulators, err: %d\n", ret);
+ dev_err(dev, "Failed to get power regulators, err: %d\n", ret);
return ret;
}
@@ -1977,7 +2036,7 @@ static int imx274_probe(struct i2c_client *client)
/* initialize regmap */
imx274->regmap = devm_regmap_init_i2c(client, &imx274_regmap_config);
if (IS_ERR(imx274->regmap)) {
- dev_err(&client->dev,
+ dev_err(dev,
"regmap init failed: %ld\n", PTR_ERR(imx274->regmap));
ret = -ENODEV;
goto err_regmap;
@@ -1994,34 +2053,32 @@ static int imx274_probe(struct i2c_client *client)
sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
ret = media_entity_pads_init(&sd->entity, 1, &imx274->pad);
if (ret < 0) {
- dev_err(&client->dev,
+ dev_err(dev,
"%s : media entity init Failed %d\n", __func__, ret);
goto err_regmap;
}
/* initialize sensor reset gpio */
- imx274->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",
+ imx274->reset_gpio = devm_gpiod_get_optional(dev, "reset",
GPIOD_OUT_HIGH);
if (IS_ERR(imx274->reset_gpio)) {
if (PTR_ERR(imx274->reset_gpio) != -EPROBE_DEFER)
- dev_err(&client->dev, "Reset GPIO not setup in DT");
+ dev_err(dev, "Reset GPIO not setup in DT");
ret = PTR_ERR(imx274->reset_gpio);
goto err_me;
}
/* power on the sensor */
- ret = imx274_power_on(&client->dev);
+ ret = imx274_power_on(dev);
if (ret < 0) {
- dev_err(&client->dev,
- "%s : imx274 power on failed\n", __func__);
+ dev_err(dev, "%s : imx274 power on failed\n", __func__);
goto err_me;
}
/* initialize controls */
ret = v4l2_ctrl_handler_init(&imx274->ctrls.handler, 4);
if (ret < 0) {
- dev_err(&client->dev,
- "%s : ctrl handler init Failed\n", __func__);
+ dev_err(dev, "%s : ctrl handler init Failed\n", __func__);
goto err_power_off;
}
@@ -2064,23 +2121,22 @@ static int imx274_probe(struct i2c_client *client)
/* register subdevice */
ret = v4l2_async_register_subdev(sd);
if (ret < 0) {
- dev_err(&client->dev,
- "%s : v4l2_async_register_subdev failed %d\n",
+ dev_err(dev, "%s : v4l2_async_register_subdev failed %d\n",
__func__, ret);
goto err_ctrls;
}
- pm_runtime_set_active(&client->dev);
- pm_runtime_enable(&client->dev);
- pm_runtime_idle(&client->dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+ pm_runtime_idle(dev);
- dev_info(&client->dev, "imx274 : imx274 probe success !\n");
+ dev_info(dev, "imx274 : imx274 probe success !\n");
return 0;
err_ctrls:
v4l2_ctrl_handler_free(&imx274->ctrls.handler);
e