Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: ov5640: check chip id

Verify that chip identifier is correct when probing.

Signed-off-by: Hugues Fruchet <hugues.fruchet@st.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>

authored by

Hugues Fruchet and committed by
Mauro Carvalho Chehab
0f7acb52 1fddc5da

+79 -16
+79 -16
drivers/media/i2c/ov5640.c
··· 1547 1547 usleep_range(5000, 10000); 1548 1548 } 1549 1549 1550 + static int ov5640_set_power_on(struct ov5640_dev *sensor) 1551 + { 1552 + struct i2c_client *client = sensor->i2c_client; 1553 + int ret; 1554 + 1555 + ret = clk_prepare_enable(sensor->xclk); 1556 + if (ret) { 1557 + dev_err(&client->dev, "%s: failed to enable clock\n", 1558 + __func__); 1559 + return ret; 1560 + } 1561 + 1562 + ret = regulator_bulk_enable(OV5640_NUM_SUPPLIES, 1563 + sensor->supplies); 1564 + if (ret) { 1565 + dev_err(&client->dev, "%s: failed to enable regulators\n", 1566 + __func__); 1567 + goto xclk_off; 1568 + } 1569 + 1570 + ov5640_reset(sensor); 1571 + ov5640_power(sensor, true); 1572 + 1573 + ret = ov5640_init_slave_id(sensor); 1574 + if (ret) 1575 + goto power_off; 1576 + 1577 + return 0; 1578 + 1579 + power_off: 1580 + ov5640_power(sensor, false); 1581 + regulator_bulk_disable(OV5640_NUM_SUPPLIES, sensor->supplies); 1582 + xclk_off: 1583 + clk_disable_unprepare(sensor->xclk); 1584 + return ret; 1585 + } 1586 + 1587 + static void ov5640_set_power_off(struct ov5640_dev *sensor) 1588 + { 1589 + ov5640_power(sensor, false); 1590 + regulator_bulk_disable(OV5640_NUM_SUPPLIES, sensor->supplies); 1591 + clk_disable_unprepare(sensor->xclk); 1592 + } 1593 + 1550 1594 static int ov5640_set_power(struct ov5640_dev *sensor, bool on) 1551 1595 { 1552 1596 int ret = 0; 1553 1597 1554 1598 if (on) { 1555 - clk_prepare_enable(sensor->xclk); 1556 - 1557 - ret = regulator_bulk_enable(OV5640_NUM_SUPPLIES, 1558 - sensor->supplies); 1599 + ret = ov5640_set_power_on(sensor); 1559 1600 if (ret) 1560 - goto xclk_off; 1561 - 1562 - ov5640_reset(sensor); 1563 - ov5640_power(sensor, true); 1564 - 1565 - ret = ov5640_init_slave_id(sensor); 1566 - if (ret) 1567 - goto power_off; 1601 + return ret; 1568 1602 1569 1603 ret = ov5640_restore_mode(sensor); 1570 1604 if (ret) ··· 1620 1586 } 1621 1587 1622 1588 power_off: 1623 - ov5640_power(sensor, false); 1624 - regulator_bulk_disable(OV5640_NUM_SUPPLIES, sensor->supplies); 1625 - xclk_off: 1626 - clk_disable_unprepare(sensor->xclk); 1589 + ov5640_set_power_off(sensor); 1627 1590 return ret; 1628 1591 } 1629 1592 ··· 2233 2202 sensor->supplies); 2234 2203 } 2235 2204 2205 + static int ov5640_check_chip_id(struct ov5640_dev *sensor) 2206 + { 2207 + struct i2c_client *client = sensor->i2c_client; 2208 + int ret = 0; 2209 + u16 chip_id; 2210 + 2211 + ret = ov5640_set_power_on(sensor); 2212 + if (ret) 2213 + return ret; 2214 + 2215 + ret = ov5640_read_reg16(sensor, OV5640_REG_CHIP_ID, &chip_id); 2216 + if (ret) { 2217 + dev_err(&client->dev, "%s: failed to read chip identifier\n", 2218 + __func__); 2219 + goto power_off; 2220 + } 2221 + 2222 + if (chip_id != 0x5640) { 2223 + dev_err(&client->dev, "%s: wrong chip identifier, expected 0x5640, got 0x%x\n", 2224 + __func__, chip_id); 2225 + ret = -ENXIO; 2226 + } 2227 + 2228 + power_off: 2229 + ov5640_set_power_off(sensor); 2230 + return ret; 2231 + } 2232 + 2236 2233 static int ov5640_probe(struct i2c_client *client, 2237 2234 const struct i2c_device_id *id) 2238 2235 { ··· 2342 2283 return ret; 2343 2284 2344 2285 mutex_init(&sensor->lock); 2286 + 2287 + ret = ov5640_check_chip_id(sensor); 2288 + if (ret) 2289 + goto entity_cleanup; 2345 2290 2346 2291 ret = ov5640_init_controls(sensor); 2347 2292 if (ret)