Skip to content

Commit 56ca3be

Browse files
bingbucaomchehab
authored andcommitted
media: imx208: Support device probe in non-zero ACPI D state
Tell ACPI device PM code that the driver supports the device being in non-zero ACPI D state when the driver's probe function is entered. Also do identification on the first access of the device, whether in probe or when starting streaming. Signed-off-by: Bingbu Cao <[email protected]> Signed-off-by: Sakari Ailus <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent ada2c4f commit 56ca3be

File tree

1 file changed

+53
-29
lines changed

1 file changed

+53
-29
lines changed

drivers/media/i2c/imx208.c

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,9 @@ struct imx208 {
296296
/* OTP data */
297297
bool otp_read;
298298
char otp_data[IMX208_OTP_SIZE];
299+
300+
/* True if the device has been identified */
301+
bool identified;
299302
};
300303

301304
static inline struct imx208 *to_imx208(struct v4l2_subdev *_sd)
@@ -619,13 +622,45 @@ static int imx208_set_pad_format(struct v4l2_subdev *sd,
619622
return 0;
620623
}
621624

625+
static int imx208_identify_module(struct imx208 *imx208)
626+
{
627+
struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);
628+
int ret;
629+
u32 val;
630+
631+
if (imx208->identified)
632+
return 0;
633+
634+
ret = imx208_read_reg(imx208, IMX208_REG_CHIP_ID,
635+
2, &val);
636+
if (ret) {
637+
dev_err(&client->dev, "failed to read chip id %x\n",
638+
IMX208_CHIP_ID);
639+
return ret;
640+
}
641+
642+
if (val != IMX208_CHIP_ID) {
643+
dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
644+
IMX208_CHIP_ID, val);
645+
return -EIO;
646+
}
647+
648+
imx208->identified = true;
649+
650+
return 0;
651+
}
652+
622653
/* Start streaming */
623654
static int imx208_start_streaming(struct imx208 *imx208)
624655
{
625656
struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);
626657
const struct imx208_reg_list *reg_list;
627658
int ret, link_freq_index;
628659

660+
ret = imx208_identify_module(imx208);
661+
if (ret)
662+
return ret;
663+
629664
/* Setup PLL */
630665
link_freq_index = imx208->cur_mode->link_freq_index;
631666
reg_list = &link_freq_configs[link_freq_index].reg_list;
@@ -752,29 +787,6 @@ static int __maybe_unused imx208_resume(struct device *dev)
752787
}
753788

754789
/* Verify chip ID */
755-
static int imx208_identify_module(struct imx208 *imx208)
756-
{
757-
struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);
758-
int ret;
759-
u32 val;
760-
761-
ret = imx208_read_reg(imx208, IMX208_REG_CHIP_ID,
762-
2, &val);
763-
if (ret) {
764-
dev_err(&client->dev, "failed to read chip id %x\n",
765-
IMX208_CHIP_ID);
766-
return ret;
767-
}
768-
769-
if (val != IMX208_CHIP_ID) {
770-
dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
771-
IMX208_CHIP_ID, val);
772-
return -EIO;
773-
}
774-
775-
return 0;
776-
}
777-
778790
static const struct v4l2_subdev_video_ops imx208_video_ops = {
779791
.s_stream = imx208_set_stream,
780792
};
@@ -813,6 +825,10 @@ static int imx208_read_otp(struct imx208 *imx208)
813825
goto out_unlock;
814826
}
815827

828+
ret = imx208_identify_module(imx208);
829+
if (ret)
830+
goto out_pm_put;
831+
816832
/* Write register address */
817833
msgs[0].addr = client->addr;
818834
msgs[0].flags = 0;
@@ -831,6 +847,7 @@ static int imx208_read_otp(struct imx208 *imx208)
831847
ret = 0;
832848
}
833849

850+
out_pm_put:
834851
pm_runtime_put(&client->dev);
835852

836853
out_unlock:
@@ -961,6 +978,7 @@ static int imx208_probe(struct i2c_client *client)
961978
{
962979
struct imx208 *imx208;
963980
int ret;
981+
bool full_power;
964982
u32 val = 0;
965983

966984
device_property_read_u32(&client->dev, "clock-frequency", &val);
@@ -978,11 +996,14 @@ static int imx208_probe(struct i2c_client *client)
978996
/* Initialize subdev */
979997
v4l2_i2c_subdev_init(&imx208->sd, client, &imx208_subdev_ops);
980998

981-
/* Check module identity */
982-
ret = imx208_identify_module(imx208);
983-
if (ret) {
984-
dev_err(&client->dev, "failed to find sensor: %d", ret);
985-
goto error_probe;
999+
full_power = acpi_dev_state_d0(&client->dev);
1000+
if (full_power) {
1001+
/* Check module identity */
1002+
ret = imx208_identify_module(imx208);
1003+
if (ret) {
1004+
dev_err(&client->dev, "failed to find sensor: %d", ret);
1005+
goto error_probe;
1006+
}
9861007
}
9871008

9881009
/* Set default mode to max resolution */
@@ -1017,7 +1038,9 @@ static int imx208_probe(struct i2c_client *client)
10171038
goto error_async_subdev;
10181039
}
10191040

1020-
pm_runtime_set_active(&client->dev);
1041+
/* Set the device's state to active if it's in D0 state. */
1042+
if (full_power)
1043+
pm_runtime_set_active(&client->dev);
10211044
pm_runtime_enable(&client->dev);
10221045
pm_runtime_idle(&client->dev);
10231046

@@ -1077,6 +1100,7 @@ static struct i2c_driver imx208_i2c_driver = {
10771100
},
10781101
.probe_new = imx208_probe,
10791102
.remove = imx208_remove,
1103+
.flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
10801104
};
10811105

10821106
module_i2c_driver(imx208_i2c_driver);

0 commit comments

Comments
 (0)