summaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil-cisco@xs4all.nl>2019-06-20 06:10:00 -0400
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>2019-06-27 07:19:43 -0400
commitb48cb35c6a7babdc317edb4c752ecf3da0691228 (patch)
treea61296034a488810fbca3247e131c6c0ebf63a4a /drivers/media
parent32a847f9fa40ec1b03ead2c514862764983ff9ca (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.c85
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}
89EXPORT_SYMBOL_GPL(cec_notifier_put); 90EXPORT_SYMBOL_GPL(cec_notifier_put);
90 91
92struct cec_notifier *
93cec_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}
114EXPORT_SYMBOL_GPL(cec_notifier_conn_register);
115
116void 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}
131EXPORT_SYMBOL_GPL(cec_notifier_conn_unregister);
132
133struct cec_notifier *
134cec_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}
154EXPORT_SYMBOL_GPL(cec_notifier_cec_adap_register);
155
156void 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}
168EXPORT_SYMBOL_GPL(cec_notifier_cec_adap_unregister);
169
91void cec_notifier_set_phys_addr(struct cec_notifier *n, u16 pa) 170void 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}
102EXPORT_SYMBOL_GPL(cec_notifier_set_phys_addr); 183EXPORT_SYMBOL_GPL(cec_notifier_set_phys_addr);
@@ -131,6 +212,10 @@ EXPORT_SYMBOL_GPL(cec_notifier_register);
131 212
132void cec_notifier_unregister(struct cec_notifier *n) 213void 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);