| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Driver for the OV5645 camera sensor. |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 14 | 15 | */ |
|---|
| 15 | 16 | |
|---|
| 16 | 17 | /* |
|---|
| 17 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 18 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 19 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 20 | | - * (at your option) any later version. |
|---|
| 21 | | - |
|---|
| 22 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 23 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 24 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 25 | | - * GNU General Public License for more details. |
|---|
| 26 | 18 | */ |
|---|
| 27 | 19 | |
|---|
| 28 | 20 | #include <linux/bitops.h> |
|---|
| .. | .. |
|---|
| 41 | 33 | #include <media/v4l2-ctrls.h> |
|---|
| 42 | 34 | #include <media/v4l2-fwnode.h> |
|---|
| 43 | 35 | #include <media/v4l2-subdev.h> |
|---|
| 44 | | - |
|---|
| 45 | | -#define OV5645_VOLTAGE_ANALOG 2800000 |
|---|
| 46 | | -#define OV5645_VOLTAGE_DIGITAL_CORE 1500000 |
|---|
| 47 | | -#define OV5645_VOLTAGE_DIGITAL_IO 1800000 |
|---|
| 48 | 36 | |
|---|
| 49 | 37 | #define OV5645_SYSTEM_CTRL0 0x3008 |
|---|
| 50 | 38 | #define OV5645_SYSTEM_CTRL0_START 0x02 |
|---|
| .. | .. |
|---|
| 73 | 61 | #define OV5645_SDE_SAT_U 0x5583 |
|---|
| 74 | 62 | #define OV5645_SDE_SAT_V 0x5584 |
|---|
| 75 | 63 | |
|---|
| 64 | +/* regulator supplies */ |
|---|
| 65 | +static const char * const ov5645_supply_name[] = { |
|---|
| 66 | + "vdddo", /* Digital I/O (1.8V) supply */ |
|---|
| 67 | + "vdda", /* Analog (2.8V) supply */ |
|---|
| 68 | + "vddd", /* Digital Core (1.5V) supply */ |
|---|
| 69 | +}; |
|---|
| 70 | + |
|---|
| 71 | +#define OV5645_NUM_SUPPLIES ARRAY_SIZE(ov5645_supply_name) |
|---|
| 72 | + |
|---|
| 76 | 73 | struct reg_value { |
|---|
| 77 | 74 | u16 reg; |
|---|
| 78 | 75 | u8 val; |
|---|
| .. | .. |
|---|
| 97 | 94 | struct v4l2_rect crop; |
|---|
| 98 | 95 | struct clk *xclk; |
|---|
| 99 | 96 | |
|---|
| 100 | | - struct regulator *io_regulator; |
|---|
| 101 | | - struct regulator *core_regulator; |
|---|
| 102 | | - struct regulator *analog_regulator; |
|---|
| 97 | + struct regulator_bulk_data supplies[OV5645_NUM_SUPPLIES]; |
|---|
| 103 | 98 | |
|---|
| 104 | 99 | const struct ov5645_mode_info *current_mode; |
|---|
| 105 | 100 | |
|---|
| .. | .. |
|---|
| 546 | 541 | }, |
|---|
| 547 | 542 | }; |
|---|
| 548 | 543 | |
|---|
| 549 | | -static int ov5645_regulators_enable(struct ov5645 *ov5645) |
|---|
| 550 | | -{ |
|---|
| 551 | | - int ret; |
|---|
| 552 | | - |
|---|
| 553 | | - ret = regulator_enable(ov5645->io_regulator); |
|---|
| 554 | | - if (ret < 0) { |
|---|
| 555 | | - dev_err(ov5645->dev, "set io voltage failed\n"); |
|---|
| 556 | | - return ret; |
|---|
| 557 | | - } |
|---|
| 558 | | - |
|---|
| 559 | | - ret = regulator_enable(ov5645->analog_regulator); |
|---|
| 560 | | - if (ret) { |
|---|
| 561 | | - dev_err(ov5645->dev, "set analog voltage failed\n"); |
|---|
| 562 | | - goto err_disable_io; |
|---|
| 563 | | - } |
|---|
| 564 | | - |
|---|
| 565 | | - ret = regulator_enable(ov5645->core_regulator); |
|---|
| 566 | | - if (ret) { |
|---|
| 567 | | - dev_err(ov5645->dev, "set core voltage failed\n"); |
|---|
| 568 | | - goto err_disable_analog; |
|---|
| 569 | | - } |
|---|
| 570 | | - |
|---|
| 571 | | - return 0; |
|---|
| 572 | | - |
|---|
| 573 | | -err_disable_analog: |
|---|
| 574 | | - regulator_disable(ov5645->analog_regulator); |
|---|
| 575 | | -err_disable_io: |
|---|
| 576 | | - regulator_disable(ov5645->io_regulator); |
|---|
| 577 | | - |
|---|
| 578 | | - return ret; |
|---|
| 579 | | -} |
|---|
| 580 | | - |
|---|
| 581 | | -static void ov5645_regulators_disable(struct ov5645 *ov5645) |
|---|
| 582 | | -{ |
|---|
| 583 | | - int ret; |
|---|
| 584 | | - |
|---|
| 585 | | - ret = regulator_disable(ov5645->core_regulator); |
|---|
| 586 | | - if (ret < 0) |
|---|
| 587 | | - dev_err(ov5645->dev, "core regulator disable failed\n"); |
|---|
| 588 | | - |
|---|
| 589 | | - ret = regulator_disable(ov5645->analog_regulator); |
|---|
| 590 | | - if (ret < 0) |
|---|
| 591 | | - dev_err(ov5645->dev, "analog regulator disable failed\n"); |
|---|
| 592 | | - |
|---|
| 593 | | - ret = regulator_disable(ov5645->io_regulator); |
|---|
| 594 | | - if (ret < 0) |
|---|
| 595 | | - dev_err(ov5645->dev, "io regulator disable failed\n"); |
|---|
| 596 | | -} |
|---|
| 597 | | - |
|---|
| 598 | 544 | static int ov5645_write_reg(struct ov5645 *ov5645, u16 reg, u8 val) |
|---|
| 599 | 545 | { |
|---|
| 600 | 546 | u8 regbuf[3]; |
|---|
| .. | .. |
|---|
| 693 | 639 | { |
|---|
| 694 | 640 | int ret; |
|---|
| 695 | 641 | |
|---|
| 696 | | - ret = ov5645_regulators_enable(ov5645); |
|---|
| 697 | | - if (ret < 0) { |
|---|
| 642 | + ret = regulator_bulk_enable(OV5645_NUM_SUPPLIES, ov5645->supplies); |
|---|
| 643 | + if (ret < 0) |
|---|
| 698 | 644 | return ret; |
|---|
| 699 | | - } |
|---|
| 700 | 645 | |
|---|
| 701 | 646 | ret = clk_prepare_enable(ov5645->xclk); |
|---|
| 702 | 647 | if (ret < 0) { |
|---|
| 703 | 648 | dev_err(ov5645->dev, "clk prepare enable failed\n"); |
|---|
| 704 | | - ov5645_regulators_disable(ov5645); |
|---|
| 649 | + regulator_bulk_disable(OV5645_NUM_SUPPLIES, ov5645->supplies); |
|---|
| 705 | 650 | return ret; |
|---|
| 706 | 651 | } |
|---|
| 707 | 652 | |
|---|
| .. | .. |
|---|
| 721 | 666 | gpiod_set_value_cansleep(ov5645->rst_gpio, 1); |
|---|
| 722 | 667 | gpiod_set_value_cansleep(ov5645->enable_gpio, 0); |
|---|
| 723 | 668 | clk_disable_unprepare(ov5645->xclk); |
|---|
| 724 | | - ov5645_regulators_disable(ov5645); |
|---|
| 669 | + regulator_bulk_disable(OV5645_NUM_SUPPLIES, ov5645->supplies); |
|---|
| 725 | 670 | } |
|---|
| 726 | 671 | |
|---|
| 727 | 672 | static int ov5645_s_power(struct v4l2_subdev *sd, int on) |
|---|
| .. | .. |
|---|
| 887 | 832 | return ret; |
|---|
| 888 | 833 | } |
|---|
| 889 | 834 | |
|---|
| 890 | | -static struct v4l2_ctrl_ops ov5645_ctrl_ops = { |
|---|
| 835 | +static const struct v4l2_ctrl_ops ov5645_ctrl_ops = { |
|---|
| 891 | 836 | .s_ctrl = ov5645_s_ctrl, |
|---|
| 892 | 837 | }; |
|---|
| 893 | 838 | |
|---|
| .. | .. |
|---|
| 1104 | 1049 | .pad = &ov5645_subdev_pad_ops, |
|---|
| 1105 | 1050 | }; |
|---|
| 1106 | 1051 | |
|---|
| 1107 | | -static int ov5645_probe(struct i2c_client *client, |
|---|
| 1108 | | - const struct i2c_device_id *id) |
|---|
| 1052 | +static int ov5645_probe(struct i2c_client *client) |
|---|
| 1109 | 1053 | { |
|---|
| 1110 | 1054 | struct device *dev = &client->dev; |
|---|
| 1111 | 1055 | struct device_node *endpoint; |
|---|
| 1112 | 1056 | struct ov5645 *ov5645; |
|---|
| 1113 | 1057 | u8 chip_id_high, chip_id_low; |
|---|
| 1058 | + unsigned int i; |
|---|
| 1114 | 1059 | u32 xclk_freq; |
|---|
| 1115 | 1060 | int ret; |
|---|
| 1116 | 1061 | |
|---|
| .. | .. |
|---|
| 1137 | 1082 | return ret; |
|---|
| 1138 | 1083 | } |
|---|
| 1139 | 1084 | |
|---|
| 1140 | | - if (ov5645->ep.bus_type != V4L2_MBUS_CSI2) { |
|---|
| 1085 | + if (ov5645->ep.bus_type != V4L2_MBUS_CSI2_DPHY) { |
|---|
| 1141 | 1086 | dev_err(dev, "invalid bus type, must be CSI2\n"); |
|---|
| 1142 | 1087 | return -EINVAL; |
|---|
| 1143 | 1088 | } |
|---|
| .. | .. |
|---|
| 1168 | 1113 | return ret; |
|---|
| 1169 | 1114 | } |
|---|
| 1170 | 1115 | |
|---|
| 1171 | | - ov5645->io_regulator = devm_regulator_get(dev, "vdddo"); |
|---|
| 1172 | | - if (IS_ERR(ov5645->io_regulator)) { |
|---|
| 1173 | | - dev_err(dev, "cannot get io regulator\n"); |
|---|
| 1174 | | - return PTR_ERR(ov5645->io_regulator); |
|---|
| 1175 | | - } |
|---|
| 1116 | + for (i = 0; i < OV5645_NUM_SUPPLIES; i++) |
|---|
| 1117 | + ov5645->supplies[i].supply = ov5645_supply_name[i]; |
|---|
| 1176 | 1118 | |
|---|
| 1177 | | - ret = regulator_set_voltage(ov5645->io_regulator, |
|---|
| 1178 | | - OV5645_VOLTAGE_DIGITAL_IO, |
|---|
| 1179 | | - OV5645_VOLTAGE_DIGITAL_IO); |
|---|
| 1180 | | - if (ret < 0) { |
|---|
| 1181 | | - dev_err(dev, "cannot set io voltage\n"); |
|---|
| 1119 | + ret = devm_regulator_bulk_get(dev, OV5645_NUM_SUPPLIES, |
|---|
| 1120 | + ov5645->supplies); |
|---|
| 1121 | + if (ret < 0) |
|---|
| 1182 | 1122 | return ret; |
|---|
| 1183 | | - } |
|---|
| 1184 | | - |
|---|
| 1185 | | - ov5645->core_regulator = devm_regulator_get(dev, "vddd"); |
|---|
| 1186 | | - if (IS_ERR(ov5645->core_regulator)) { |
|---|
| 1187 | | - dev_err(dev, "cannot get core regulator\n"); |
|---|
| 1188 | | - return PTR_ERR(ov5645->core_regulator); |
|---|
| 1189 | | - } |
|---|
| 1190 | | - |
|---|
| 1191 | | - ret = regulator_set_voltage(ov5645->core_regulator, |
|---|
| 1192 | | - OV5645_VOLTAGE_DIGITAL_CORE, |
|---|
| 1193 | | - OV5645_VOLTAGE_DIGITAL_CORE); |
|---|
| 1194 | | - if (ret < 0) { |
|---|
| 1195 | | - dev_err(dev, "cannot set core voltage\n"); |
|---|
| 1196 | | - return ret; |
|---|
| 1197 | | - } |
|---|
| 1198 | | - |
|---|
| 1199 | | - ov5645->analog_regulator = devm_regulator_get(dev, "vdda"); |
|---|
| 1200 | | - if (IS_ERR(ov5645->analog_regulator)) { |
|---|
| 1201 | | - dev_err(dev, "cannot get analog regulator\n"); |
|---|
| 1202 | | - return PTR_ERR(ov5645->analog_regulator); |
|---|
| 1203 | | - } |
|---|
| 1204 | | - |
|---|
| 1205 | | - ret = regulator_set_voltage(ov5645->analog_regulator, |
|---|
| 1206 | | - OV5645_VOLTAGE_ANALOG, |
|---|
| 1207 | | - OV5645_VOLTAGE_ANALOG); |
|---|
| 1208 | | - if (ret < 0) { |
|---|
| 1209 | | - dev_err(dev, "cannot set analog voltage\n"); |
|---|
| 1210 | | - return ret; |
|---|
| 1211 | | - } |
|---|
| 1212 | 1123 | |
|---|
| 1213 | 1124 | ov5645->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH); |
|---|
| 1214 | 1125 | if (IS_ERR(ov5645->enable_gpio)) { |
|---|
| .. | .. |
|---|
| 1373 | 1284 | .of_match_table = of_match_ptr(ov5645_of_match), |
|---|
| 1374 | 1285 | .name = "ov5645", |
|---|
| 1375 | 1286 | }, |
|---|
| 1376 | | - .probe = ov5645_probe, |
|---|
| 1287 | + .probe_new = ov5645_probe, |
|---|
| 1377 | 1288 | .remove = ov5645_remove, |
|---|
| 1378 | 1289 | .id_table = ov5645_id, |
|---|
| 1379 | 1290 | }; |
|---|