diff options
author | Hans Verkuil <hverkuil-cisco@xs4all.nl> | 2019-06-20 06:10:00 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | 2019-06-27 07:19:43 -0400 |
commit | b48cb35c6a7babdc317edb4c752ecf3da0691228 (patch) | |
tree | a61296034a488810fbca3247e131c6c0ebf63a4a /drivers/media | |
parent | 32a847f9fa40ec1b03ead2c514862764983ff9ca (diff) |
media: cec-notifier: add new notifier functions
In order to support multiple CEC devices for an HDMI connector,
and to support cec_connector_info, drivers should use either a
cec_notifier_conn_(un)register pair of functions (HDMI drivers)
or a cec_notifier_cec_adap_(un)register pair (CEC adapter drivers).
This replaces cec_notifier_get_conn/cec_notifier_put.
For CEC adapters it is also no longer needed to call cec_notifier_register,
cec_register_cec_notifier and cec_notifier_unregister. This is now
all handled internally by the new functions.
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/cec/cec-notifier.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/drivers/media/cec/cec-notifier.c b/drivers/media/cec/cec-notifier.c index f72b19c351dd..52a867bde15f 100644 --- a/drivers/media/cec/cec-notifier.c +++ b/drivers/media/cec/cec-notifier.c | |||
@@ -22,6 +22,7 @@ struct cec_notifier { | |||
22 | struct list_head head; | 22 | struct list_head head; |
23 | struct kref kref; | 23 | struct kref kref; |
24 | struct device *hdmi_dev; | 24 | struct device *hdmi_dev; |
25 | struct cec_connector_info conn_info; | ||
25 | const char *conn_name; | 26 | const char *conn_name; |
26 | struct cec_adapter *cec_adap; | 27 | struct cec_adapter *cec_adap; |
27 | void (*callback)(struct cec_adapter *adap, u16 pa); | 28 | void (*callback)(struct cec_adapter *adap, u16 pa); |
@@ -88,6 +89,84 @@ void cec_notifier_put(struct cec_notifier *n) | |||
88 | } | 89 | } |
89 | EXPORT_SYMBOL_GPL(cec_notifier_put); | 90 | EXPORT_SYMBOL_GPL(cec_notifier_put); |
90 | 91 | ||
92 | struct cec_notifier * | ||
93 | cec_notifier_conn_register(struct device *hdmi_dev, const char *conn_name, | ||
94 | const struct cec_connector_info *conn_info) | ||
95 | { | ||
96 | struct cec_notifier *n = cec_notifier_get_conn(hdmi_dev, conn_name); | ||
97 | |||
98 | if (!n) | ||
99 | return n; | ||
100 | |||
101 | mutex_lock(&n->lock); | ||
102 | n->phys_addr = CEC_PHYS_ADDR_INVALID; | ||
103 | if (conn_info) | ||
104 | n->conn_info = *conn_info; | ||
105 | else | ||
106 | memset(&n->conn_info, 0, sizeof(n->conn_info)); | ||
107 | if (n->cec_adap) { | ||
108 | cec_phys_addr_invalidate(n->cec_adap); | ||
109 | cec_s_conn_info(n->cec_adap, conn_info); | ||
110 | } | ||
111 | mutex_unlock(&n->lock); | ||
112 | return n; | ||
113 | } | ||
114 | EXPORT_SYMBOL_GPL(cec_notifier_conn_register); | ||
115 | |||
116 | void cec_notifier_conn_unregister(struct cec_notifier *n) | ||
117 | { | ||
118 | if (!n) | ||
119 | return; | ||
120 | |||
121 | mutex_lock(&n->lock); | ||
122 | memset(&n->conn_info, 0, sizeof(n->conn_info)); | ||
123 | n->phys_addr = CEC_PHYS_ADDR_INVALID; | ||
124 | if (n->cec_adap) { | ||
125 | cec_phys_addr_invalidate(n->cec_adap); | ||
126 | cec_s_conn_info(n->cec_adap, NULL); | ||
127 | } | ||
128 | mutex_unlock(&n->lock); | ||
129 | cec_notifier_put(n); | ||
130 | } | ||
131 | EXPORT_SYMBOL_GPL(cec_notifier_conn_unregister); | ||
132 | |||
133 | struct cec_notifier * | ||
134 | cec_notifier_cec_adap_register(struct device *hdmi_dev, const char *conn_name, | ||
135 | struct cec_adapter *adap) | ||
136 | { | ||
137 | struct cec_notifier *n; | ||
138 | |||
139 | if (WARN_ON(!adap)) | ||
140 | return NULL; | ||
141 | |||
142 | n = cec_notifier_get_conn(hdmi_dev, conn_name); | ||
143 | if (!n) | ||
144 | return n; | ||
145 | |||
146 | mutex_lock(&n->lock); | ||
147 | n->cec_adap = adap; | ||
148 | adap->conn_info = n->conn_info; | ||
149 | adap->notifier = n; | ||
150 | cec_s_phys_addr(adap, n->phys_addr, false); | ||
151 | mutex_unlock(&n->lock); | ||
152 | return n; | ||
153 | } | ||
154 | EXPORT_SYMBOL_GPL(cec_notifier_cec_adap_register); | ||
155 | |||
156 | void cec_notifier_cec_adap_unregister(struct cec_notifier *n) | ||
157 | { | ||
158 | if (!n) | ||
159 | return; | ||
160 | |||
161 | mutex_lock(&n->lock); | ||
162 | n->cec_adap->notifier = NULL; | ||
163 | n->cec_adap = NULL; | ||
164 | n->callback = NULL; | ||
165 | mutex_unlock(&n->lock); | ||
166 | cec_notifier_put(n); | ||
167 | } | ||
168 | EXPORT_SYMBOL_GPL(cec_notifier_cec_adap_unregister); | ||
169 | |||
91 | void cec_notifier_set_phys_addr(struct cec_notifier *n, u16 pa) | 170 | void cec_notifier_set_phys_addr(struct cec_notifier *n, u16 pa) |
92 | { | 171 | { |
93 | if (n == NULL) | 172 | if (n == NULL) |
@@ -97,6 +176,8 @@ void cec_notifier_set_phys_addr(struct cec_notifier *n, u16 pa) | |||
97 | n->phys_addr = pa; | 176 | n->phys_addr = pa; |
98 | if (n->callback) | 177 | if (n->callback) |
99 | n->callback(n->cec_adap, n->phys_addr); | 178 | n->callback(n->cec_adap, n->phys_addr); |
179 | else if (n->cec_adap) | ||
180 | cec_s_phys_addr(n->cec_adap, n->phys_addr, false); | ||
100 | mutex_unlock(&n->lock); | 181 | mutex_unlock(&n->lock); |
101 | } | 182 | } |
102 | EXPORT_SYMBOL_GPL(cec_notifier_set_phys_addr); | 183 | EXPORT_SYMBOL_GPL(cec_notifier_set_phys_addr); |
@@ -131,6 +212,10 @@ EXPORT_SYMBOL_GPL(cec_notifier_register); | |||
131 | 212 | ||
132 | void cec_notifier_unregister(struct cec_notifier *n) | 213 | void cec_notifier_unregister(struct cec_notifier *n) |
133 | { | 214 | { |
215 | /* Do nothing unless cec_notifier_register was called first */ | ||
216 | if (!n->callback) | ||
217 | return; | ||
218 | |||
134 | mutex_lock(&n->lock); | 219 | mutex_lock(&n->lock); |
135 | n->callback = NULL; | 220 | n->callback = NULL; |
136 | mutex_unlock(&n->lock); | 221 | mutex_unlock(&n->lock); |