summaryrefslogtreecommitdiffstats
path: root/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0482-media-i2c-max9286-ti9x4-power-down-POCs-on-reboot.patch
blob: ab493586123839f225dc5e723105d96f7ce25d57 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
From cc34c21f572727e49f69e10b761bc44d3addf520 Mon Sep 17 00:00:00 2001
From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
Date: Wed, 4 Mar 2020 17:32:44 +0300
Subject: [PATCH] media: i2c: max9286,ti9x4: power down POCs on reboot

Power down all POCs on reboot/shutdown/halt

Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
---
 drivers/media/i2c/soc_camera/max9286.c | 23 +++++++++++++++++++++++
 drivers/media/i2c/soc_camera/ti9x4.c   | 22 ++++++++++++++++++++++
 2 files changed, 45 insertions(+)

diff --git a/drivers/media/i2c/soc_camera/max9286.c b/drivers/media/i2c/soc_camera/max9286.c
index 343b8ab..05247ff 100644
--- a/drivers/media/i2c/soc_camera/max9286.c
+++ b/drivers/media/i2c/soc_camera/max9286.c
@@ -15,6 +15,7 @@
 #include <linux/notifier.h>
 #include <linux/of_gpio.h>
 #include <linux/of_graph.h>
+#include <linux/reboot.h>
 #include <linux/videodev2.h>
 
 #include <media/v4l2-common.h>
@@ -71,6 +72,7 @@ struct max9286_priv {
 	int			max9271_addr_map[4];
 	int			ser_id;
 	struct gpio_desc	*poc_gpio[4]; /* PoC power supply */
+	struct notifier_block	reboot_notifier;
 
 	/* link statistic */
 	int			prbserr[4];
@@ -643,6 +645,19 @@ static int max9286_registered_async(struct v4l2_subdev *sd)
 	return 0;
 }
 
+static int max9286_reboot_notifier(struct notifier_block *nb, unsigned long event, void *buf)
+{
+	struct max9286_priv *priv = container_of(nb, struct max9286_priv, reboot_notifier);
+	int idx;
+
+	for (idx = 0; idx < priv->links; idx++) {
+		if (!IS_ERR(priv->poc_gpio[idx]))
+			gpiod_direction_output(priv->poc_gpio[idx], 0); /* POC power off */
+	}
+
+	return NOTIFY_OK;
+}
+
 static struct v4l2_subdev_core_ops max9286_subdev_core_ops = {
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.g_register		= max9286_g_register,
@@ -996,6 +1011,13 @@ static int max9286_probe(struct i2c_client *client,
 			goto out;
 	}
 
+	priv->reboot_notifier.notifier_call = max9286_reboot_notifier;
+	err = register_reboot_notifier(&priv->reboot_notifier);
+	if (err) {
+		dev_err(&client->dev, "failed to register reboot notifier\n");
+		goto out;
+	}
+
 	err = sysfs_create_group(&client->dev.kobj,
                                 &max9286_group);
         if (err < 0)
@@ -1010,6 +1032,7 @@ static int max9286_remove(struct i2c_client *client)
 	int i;
 
 	sysfs_remove_group(&client->dev.kobj,  &max9286_group);
+	unregister_reboot_notifier(&priv->reboot_notifier);
 
 	for (i = 0; i < 4; i++) {
 		v4l2_async_unregister_subdev(&priv->sd[i]);
diff --git a/drivers/media/i2c/soc_camera/ti9x4.c b/drivers/media/i2c/soc_camera/ti9x4.c
index 9004bb1..627612a 100644
--- a/drivers/media/i2c/soc_camera/ti9x4.c
+++ b/drivers/media/i2c/soc_camera/ti9x4.c
@@ -15,6 +15,7 @@
 #include <linux/notifier.h>
 #include <linux/of_gpio.h>
 #include <linux/of_graph.h>
+#include <linux/reboot.h>
 #include <linux/videodev2.h>
 
 #include <media/v4l2-common.h>
@@ -52,6 +53,7 @@ struct ti9x4_priv {
 	struct gpio_desc	*pwen; /* chip power en */
 	struct gpio_desc	*poc_gpio[4]; /* PoC power supply */
 	struct v4l2_clk		*ref_clk; /* ref clock */
+	struct notifier_block	reboot_notifier;
 };
 
 static int ser_id;
@@ -420,6 +422,19 @@ static int ti9x4_registered_async(struct v4l2_subdev *sd)
 	return 0;
 }
 
+static int ti9x4_reboot_notifier(struct notifier_block *nb, unsigned long event, void *buf)
+{
+	struct ti9x4_priv *priv = container_of(nb, struct ti9x4_priv, reboot_notifier);
+	int idx;
+
+	for (idx = 0; idx < priv->links; idx++) {
+		if (!IS_ERR(priv->poc_gpio[idx]))
+			gpiod_direction_output(priv->poc_gpio[idx], 0); /* POC power off */
+	}
+
+	return NOTIFY_OK;
+}
+
 static struct v4l2_subdev_core_ops ti9x4_subdev_core_ops = {
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.g_register		= ti9x4_g_register,
@@ -676,6 +691,11 @@ static int ti9x4_probe(struct i2c_client *client,
 			goto out;
 	}
 
+	priv->reboot_notifier.notifier_call = ti9x4_reboot_notifier;
+	err = register_reboot_notifier(&priv->reboot_notifier);
+	if (err)
+		dev_err(&client->dev, "failed to register reboot notifier\n");
+
 out:
 	return err;
 }
@@ -685,6 +705,8 @@ static int ti9x4_remove(struct i2c_client *client)
 	struct ti9x4_priv *priv = i2c_get_clientdata(client);
 	int i;
 
+	unregister_reboot_notifier(&priv->reboot_notifier);
+
 	for (i = 0; i < priv->links; i++) {
 		v4l2_async_unregister_subdev(&priv->sd[i]);
 		v4l2_device_unregister_subdev(&priv->sd[i]);
-- 
2.7.4