Skip to content

Commit 0e014f1

Browse files
bingbucaomchehab
authored andcommitted
media: ov8856: 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 cbe0b3a commit 0e014f1

File tree

1 file changed

+89
-73
lines changed

1 file changed

+89
-73
lines changed

drivers/media/i2c/ov8856.c

Lines changed: 89 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1445,6 +1445,9 @@ struct ov8856 {
14451445

14461446
const struct ov8856_lane_cfg *priv_lane;
14471447
u8 modes_size;
1448+
1449+
/* True if the device has been identified */
1450+
bool identified;
14481451
};
14491452

14501453
struct ov8856_lane_cfg {
@@ -1685,6 +1688,71 @@ static int ov8856_write_reg_list(struct ov8856 *ov8856,
16851688
return 0;
16861689
}
16871690

1691+
static int ov8856_identify_module(struct ov8856 *ov8856)
1692+
{
1693+
struct i2c_client *client = v4l2_get_subdevdata(&ov8856->sd);
1694+
int ret;
1695+
u32 val;
1696+
1697+
if (ov8856->identified)
1698+
return 0;
1699+
1700+
ret = ov8856_read_reg(ov8856, OV8856_REG_CHIP_ID,
1701+
OV8856_REG_VALUE_24BIT, &val);
1702+
if (ret)
1703+
return ret;
1704+
1705+
if (val != OV8856_CHIP_ID) {
1706+
dev_err(&client->dev, "chip id mismatch: %x!=%x",
1707+
OV8856_CHIP_ID, val);
1708+
return -ENXIO;
1709+
}
1710+
1711+
ret = ov8856_write_reg(ov8856, OV8856_REG_MODE_SELECT,
1712+
OV8856_REG_VALUE_08BIT, OV8856_MODE_STREAMING);
1713+
if (ret)
1714+
return ret;
1715+
1716+
ret = ov8856_write_reg(ov8856, OV8856_OTP_MODE_CTRL,
1717+
OV8856_REG_VALUE_08BIT, OV8856_OTP_MODE_AUTO);
1718+
if (ret) {
1719+
dev_err(&client->dev, "failed to set otp mode");
1720+
return ret;
1721+
}
1722+
1723+
ret = ov8856_write_reg(ov8856, OV8856_OTP_LOAD_CTRL,
1724+
OV8856_REG_VALUE_08BIT,
1725+
OV8856_OTP_LOAD_CTRL_ENABLE);
1726+
if (ret) {
1727+
dev_err(&client->dev, "failed to enable load control");
1728+
return ret;
1729+
}
1730+
1731+
ret = ov8856_read_reg(ov8856, OV8856_MODULE_REVISION,
1732+
OV8856_REG_VALUE_08BIT, &val);
1733+
if (ret) {
1734+
dev_err(&client->dev, "failed to read module revision");
1735+
return ret;
1736+
}
1737+
1738+
dev_info(&client->dev, "OV8856 revision %x (%s) at address 0x%02x\n",
1739+
val,
1740+
val == OV8856_2A_MODULE ? "2A" :
1741+
val == OV8856_1B_MODULE ? "1B" : "unknown revision",
1742+
client->addr);
1743+
1744+
ret = ov8856_write_reg(ov8856, OV8856_REG_MODE_SELECT,
1745+
OV8856_REG_VALUE_08BIT, OV8856_MODE_STANDBY);
1746+
if (ret) {
1747+
dev_err(&client->dev, "failed to exit streaming mode");
1748+
return ret;
1749+
}
1750+
1751+
ov8856->identified = true;
1752+
1753+
return 0;
1754+
}
1755+
16881756
static int ov8856_update_digital_gain(struct ov8856 *ov8856, u32 d_gain)
16891757
{
16901758
int ret;
@@ -1969,6 +2037,10 @@ static int ov8856_start_streaming(struct ov8856 *ov8856)
19692037
const struct ov8856_reg_list *reg_list;
19702038
int link_freq_index, ret;
19712039

2040+
ret = ov8856_identify_module(ov8856);
2041+
if (ret)
2042+
return ret;
2043+
19722044
link_freq_index = ov8856->cur_mode->link_freq_index;
19732045
reg_list = &ov8856->priv_lane->link_freq_configs[link_freq_index].reg_list;
19742046

@@ -2276,65 +2348,6 @@ static const struct v4l2_subdev_internal_ops ov8856_internal_ops = {
22762348
.open = ov8856_open,
22772349
};
22782350

2279-
static int ov8856_identify_module(struct ov8856 *ov8856)
2280-
{
2281-
struct i2c_client *client = v4l2_get_subdevdata(&ov8856->sd);
2282-
int ret;
2283-
u32 val;
2284-
2285-
ret = ov8856_read_reg(ov8856, OV8856_REG_CHIP_ID,
2286-
OV8856_REG_VALUE_24BIT, &val);
2287-
if (ret)
2288-
return ret;
2289-
2290-
if (val != OV8856_CHIP_ID) {
2291-
dev_err(&client->dev, "chip id mismatch: %x!=%x",
2292-
OV8856_CHIP_ID, val);
2293-
return -ENXIO;
2294-
}
2295-
2296-
ret = ov8856_write_reg(ov8856, OV8856_REG_MODE_SELECT,
2297-
OV8856_REG_VALUE_08BIT, OV8856_MODE_STREAMING);
2298-
if (ret)
2299-
return ret;
2300-
2301-
ret = ov8856_write_reg(ov8856, OV8856_OTP_MODE_CTRL,
2302-
OV8856_REG_VALUE_08BIT, OV8856_OTP_MODE_AUTO);
2303-
if (ret) {
2304-
dev_err(&client->dev, "failed to set otp mode");
2305-
return ret;
2306-
}
2307-
2308-
ret = ov8856_write_reg(ov8856, OV8856_OTP_LOAD_CTRL,
2309-
OV8856_REG_VALUE_08BIT,
2310-
OV8856_OTP_LOAD_CTRL_ENABLE);
2311-
if (ret) {
2312-
dev_err(&client->dev, "failed to enable load control");
2313-
return ret;
2314-
}
2315-
2316-
ret = ov8856_read_reg(ov8856, OV8856_MODULE_REVISION,
2317-
OV8856_REG_VALUE_08BIT, &val);
2318-
if (ret) {
2319-
dev_err(&client->dev, "failed to read module revision");
2320-
return ret;
2321-
}
2322-
2323-
dev_info(&client->dev, "OV8856 revision %x (%s) at address 0x%02x\n",
2324-
val,
2325-
val == OV8856_2A_MODULE ? "2A" :
2326-
val == OV8856_1B_MODULE ? "1B" : "unknown revision",
2327-
client->addr);
2328-
2329-
ret = ov8856_write_reg(ov8856, OV8856_REG_MODE_SELECT,
2330-
OV8856_REG_VALUE_08BIT, OV8856_MODE_STANDBY);
2331-
if (ret) {
2332-
dev_err(&client->dev, "failed to exit streaming mode");
2333-
return ret;
2334-
}
2335-
2336-
return 0;
2337-
}
23382351

23392352
static int ov8856_get_hwcfg(struct ov8856 *ov8856, struct device *dev)
23402353
{
@@ -2458,6 +2471,7 @@ static int ov8856_probe(struct i2c_client *client)
24582471
{
24592472
struct ov8856 *ov8856;
24602473
int ret;
2474+
bool full_power;
24612475

24622476
ov8856 = devm_kzalloc(&client->dev, sizeof(*ov8856), GFP_KERNEL);
24632477
if (!ov8856)
@@ -2472,16 +2486,19 @@ static int ov8856_probe(struct i2c_client *client)
24722486

24732487
v4l2_i2c_subdev_init(&ov8856->sd, client, &ov8856_subdev_ops);
24742488

2475-
ret = __ov8856_power_on(ov8856);
2476-
if (ret) {
2477-
dev_err(&client->dev, "failed to power on\n");
2478-
return ret;
2479-
}
2489+
full_power = acpi_dev_state_d0(&client->dev);
2490+
if (full_power) {
2491+
ret = __ov8856_power_on(ov8856);
2492+
if (ret) {
2493+
dev_err(&client->dev, "failed to power on\n");
2494+
return ret;
2495+
}
24802496

2481-
ret = ov8856_identify_module(ov8856);
2482-
if (ret) {
2483-
dev_err(&client->dev, "failed to find sensor: %d", ret);
2484-
goto probe_power_off;
2497+
ret = ov8856_identify_module(ov8856);
2498+
if (ret) {
2499+
dev_err(&client->dev, "failed to find sensor: %d", ret);
2500+
goto probe_power_off;
2501+
}
24852502
}
24862503

24872504
mutex_init(&ov8856->mutex);
@@ -2511,11 +2528,9 @@ static int ov8856_probe(struct i2c_client *client)
25112528
goto probe_error_media_entity_cleanup;
25122529
}
25132530

2514-
/*
2515-
* Device is already turned on by i2c-core with ACPI domain PM.
2516-
* Enable runtime PM and turn off the device.
2517-
*/
2518-
pm_runtime_set_active(&client->dev);
2531+
/* Set the device's state to active if it's in D0 state. */
2532+
if (full_power)
2533+
pm_runtime_set_active(&client->dev);
25192534
pm_runtime_enable(&client->dev);
25202535
pm_runtime_idle(&client->dev);
25212536

@@ -2562,6 +2577,7 @@ static struct i2c_driver ov8856_i2c_driver = {
25622577
},
25632578
.probe_new = ov8856_probe,
25642579
.remove = ov8856_remove,
2580+
.flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
25652581
};
25662582

25672583
module_i2c_driver(ov8856_i2c_driver);

0 commit comments

Comments
 (0)