Skip to content

Commit 0c2c7a1

Browse files
robertfossmchehab
authored andcommitted
media: ov8856: Add devicetree support
Add match table, enable ov8856_probe() to support both ACPI and DT modes. ACPI and DT modes are primarily distinguished from by checking for ACPI mode and by having resource like be NULL. Signed-off-by: Robert Foss <[email protected]> Signed-off-by: Sakari Ailus <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent 932300e commit 0c2c7a1

File tree

1 file changed

+124
-14
lines changed

1 file changed

+124
-14
lines changed

drivers/media/i2c/ov8856.c

Lines changed: 124 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33

44
#include <asm/unaligned.h>
55
#include <linux/acpi.h>
6+
#include <linux/clk.h>
67
#include <linux/delay.h>
8+
#include <linux/gpio/consumer.h>
79
#include <linux/i2c.h>
810
#include <linux/module.h>
911
#include <linux/pm_runtime.h>
12+
#include <linux/regulator/consumer.h>
1013
#include <media/v4l2-ctrls.h>
1114
#include <media/v4l2-device.h>
1215
#include <media/v4l2-fwnode.h>
@@ -18,7 +21,7 @@
1821
#define OV8856_LINK_FREQ_360MHZ 360000000ULL
1922
#define OV8856_LINK_FREQ_180MHZ 180000000ULL
2023
#define OV8856_SCLK 144000000ULL
21-
#define OV8856_MCLK 19200000
24+
#define OV8856_XVCLK_19_2 19200000
2225
#define OV8856_DATA_LANES 4
2326
#define OV8856_RGB_DEPTH 10
2427

@@ -64,6 +67,12 @@
6467

6568
#define to_ov8856(_sd) container_of(_sd, struct ov8856, sd)
6669

70+
static const char * const ov8856_supply_names[] = {
71+
"dovdd", /* Digital I/O power */
72+
"avdd", /* Analog power */
73+
"dvdd", /* Digital core power */
74+
};
75+
6776
enum {
6877
OV8856_LINK_FREQ_720MBPS,
6978
OV8856_LINK_FREQ_360MBPS,
@@ -566,6 +575,10 @@ struct ov8856 {
566575
struct media_pad pad;
567576
struct v4l2_ctrl_handler ctrl_handler;
568577

578+
struct clk *xvclk;
579+
struct gpio_desc *reset_gpio;
580+
struct regulator_bulk_data supplies[ARRAY_SIZE(ov8856_supply_names)];
581+
569582
/* V4L2 Controls */
570583
struct v4l2_ctrl *link_freq;
571584
struct v4l2_ctrl *pixel_rate;
@@ -908,6 +921,57 @@ static int ov8856_set_stream(struct v4l2_subdev *sd, int enable)
908921
return ret;
909922
}
910923

924+
static int __ov8856_power_on(struct ov8856 *ov8856)
925+
{
926+
struct i2c_client *client = v4l2_get_subdevdata(&ov8856->sd);
927+
int ret;
928+
929+
if (is_acpi_node(dev_fwnode(&client->dev)))
930+
return 0;
931+
932+
ret = clk_prepare_enable(ov8856->xvclk);
933+
if (ret < 0) {
934+
dev_err(&client->dev, "failed to enable xvclk\n");
935+
return ret;
936+
}
937+
938+
if (ov8856->reset_gpio) {
939+
gpiod_set_value_cansleep(ov8856->reset_gpio, 1);
940+
usleep_range(1000, 2000);
941+
}
942+
943+
ret = regulator_bulk_enable(ARRAY_SIZE(ov8856_supply_names),
944+
ov8856->supplies);
945+
if (ret < 0) {
946+
dev_err(&client->dev, "failed to enable regulators\n");
947+
goto disable_clk;
948+
}
949+
950+
gpiod_set_value_cansleep(ov8856->reset_gpio, 0);
951+
usleep_range(1500, 1800);
952+
953+
return 0;
954+
955+
disable_clk:
956+
gpiod_set_value_cansleep(ov8856->reset_gpio, 1);
957+
clk_disable_unprepare(ov8856->xvclk);
958+
959+
return ret;
960+
}
961+
962+
static void __ov8856_power_off(struct ov8856 *ov8856)
963+
{
964+
struct i2c_client *client = v4l2_get_subdevdata(&ov8856->sd);
965+
966+
if (is_acpi_node(dev_fwnode(&client->dev)))
967+
return;
968+
969+
gpiod_set_value_cansleep(ov8856->reset_gpio, 1);
970+
regulator_bulk_disable(ARRAY_SIZE(ov8856_supply_names),
971+
ov8856->supplies);
972+
clk_disable_unprepare(ov8856->xvclk);
973+
}
974+
911975
static int __maybe_unused ov8856_suspend(struct device *dev)
912976
{
913977
struct i2c_client *client = to_i2c_client(dev);
@@ -918,6 +982,7 @@ static int __maybe_unused ov8856_suspend(struct device *dev)
918982
if (ov8856->streaming)
919983
ov8856_stop_streaming(ov8856);
920984

985+
__ov8856_power_off(ov8856);
921986
mutex_unlock(&ov8856->mutex);
922987

923988
return 0;
@@ -931,6 +996,8 @@ static int __maybe_unused ov8856_resume(struct device *dev)
931996
int ret;
932997

933998
mutex_lock(&ov8856->mutex);
999+
1000+
__ov8856_power_on(ov8856);
9341001
if (ov8856->streaming) {
9351002
ret = ov8856_start_streaming(ov8856);
9361003
if (ret) {
@@ -1092,29 +1159,53 @@ static int ov8856_identify_module(struct ov8856 *ov8856)
10921159
return 0;
10931160
}
10941161

1095-
static int ov8856_check_hwcfg(struct device *dev)
1162+
static int ov8856_get_hwcfg(struct ov8856 *ov8856, struct device *dev)
10961163
{
10971164
struct fwnode_handle *ep;
10981165
struct fwnode_handle *fwnode = dev_fwnode(dev);
10991166
struct v4l2_fwnode_endpoint bus_cfg = {
11001167
.bus_type = V4L2_MBUS_CSI2_DPHY
11011168
};
1102-
u32 mclk;
1169+
u32 xvclk_rate;
11031170
int ret;
11041171
unsigned int i, j;
11051172

11061173
if (!fwnode)
11071174
return -ENXIO;
11081175

1109-
ret = fwnode_property_read_u32(fwnode, "clock-frequency", &mclk);
1176+
ret = fwnode_property_read_u32(fwnode, "clock-frequency", &xvclk_rate);
11101177
if (ret)
11111178
return ret;
11121179

1113-
if (mclk != OV8856_MCLK) {
1114-
dev_err(dev, "external clock %d is not supported", mclk);
1115-
return -EINVAL;
1180+
if (!is_acpi_node(fwnode)) {
1181+
ov8856->xvclk = devm_clk_get(dev, "xvclk");
1182+
if (IS_ERR(ov8856->xvclk)) {
1183+
dev_err(dev, "could not get xvclk clock (%pe)\n",
1184+
ov8856->xvclk);
1185+
return PTR_ERR(ov8856->xvclk);
1186+
}
1187+
1188+
clk_set_rate(ov8856->xvclk, xvclk_rate);
1189+
xvclk_rate = clk_get_rate(ov8856->xvclk);
11161190
}
11171191

1192+
if (xvclk_rate != OV8856_XVCLK_19_2)
1193+
dev_warn(dev, "external clock rate %u is unsupported",
1194+
xvclk_rate);
1195+
1196+
ov8856->reset_gpio = devm_gpiod_get_optional(dev, "reset",
1197+
GPIOD_OUT_LOW);
1198+
if (IS_ERR(ov8856->reset_gpio))
1199+
return PTR_ERR(ov8856->reset_gpio);
1200+
1201+
for (i = 0; i < ARRAY_SIZE(ov8856_supply_names); i++)
1202+
ov8856->supplies[i].supply = ov8856_supply_names[i];
1203+
1204+
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ov8856_supply_names),
1205+
ov8856->supplies);
1206+
if (ret)
1207+
return ret;
1208+
11181209
ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
11191210
if (!ep)
11201211
return -ENXIO;
@@ -1169,6 +1260,8 @@ static int ov8856_remove(struct i2c_client *client)
11691260
pm_runtime_disable(&client->dev);
11701261
mutex_destroy(&ov8856->mutex);
11711262

1263+
__ov8856_power_off(ov8856);
1264+
11721265
return 0;
11731266
}
11741267

@@ -1177,22 +1270,29 @@ static int ov8856_probe(struct i2c_client *client)
11771270
struct ov8856 *ov8856;
11781271
int ret;
11791272

1180-
ret = ov8856_check_hwcfg(&client->dev);
1273+
ov8856 = devm_kzalloc(&client->dev, sizeof(*ov8856), GFP_KERNEL);
1274+
if (!ov8856)
1275+
return -ENOMEM;
1276+
1277+
ret = ov8856_get_hwcfg(ov8856, &client->dev);
11811278
if (ret) {
1182-
dev_err(&client->dev, "failed to check HW configuration: %d",
1279+
dev_err(&client->dev, "failed to get HW configuration: %d",
11831280
ret);
11841281
return ret;
11851282
}
11861283

1187-
ov8856 = devm_kzalloc(&client->dev, sizeof(*ov8856), GFP_KERNEL);
1188-
if (!ov8856)
1189-
return -ENOMEM;
1190-
11911284
v4l2_i2c_subdev_init(&ov8856->sd, client, &ov8856_subdev_ops);
1285+
1286+
ret = __ov8856_power_on(ov8856);
1287+
if (ret) {
1288+
dev_err(&client->dev, "failed to power on\n");
1289+
return ret;
1290+
}
1291+
11921292
ret = ov8856_identify_module(ov8856);
11931293
if (ret) {
11941294
dev_err(&client->dev, "failed to find sensor: %d", ret);
1195-
return ret;
1295+
goto probe_power_off;
11961296
}
11971297

11981298
mutex_init(&ov8856->mutex);
@@ -1238,6 +1338,9 @@ static int ov8856_probe(struct i2c_client *client)
12381338
v4l2_ctrl_handler_free(ov8856->sd.ctrl_handler);
12391339
mutex_destroy(&ov8856->mutex);
12401340

1341+
probe_power_off:
1342+
__ov8856_power_off(ov8856);
1343+
12411344
return ret;
12421345
}
12431346

@@ -1254,11 +1357,18 @@ static const struct acpi_device_id ov8856_acpi_ids[] = {
12541357
MODULE_DEVICE_TABLE(acpi, ov8856_acpi_ids);
12551358
#endif
12561359

1360+
static const struct of_device_id ov8856_of_match[] = {
1361+
{ .compatible = "ovti,ov8856" },
1362+
{ /* sentinel */ }
1363+
};
1364+
MODULE_DEVICE_TABLE(of, ov8856_of_match);
1365+
12571366
static struct i2c_driver ov8856_i2c_driver = {
12581367
.driver = {
12591368
.name = "ov8856",
12601369
.pm = &ov8856_pm_ops,
12611370
.acpi_match_table = ACPI_PTR(ov8856_acpi_ids),
1371+
.of_match_table = ov8856_of_match,
12621372
},
12631373
.probe_new = ov8856_probe,
12641374
.remove = ov8856_remove,

0 commit comments

Comments
 (0)