media: vivid: add CEC pin monitoring emulation
[sfrench/cifs-2.6.git] / drivers / media / platform / vivid / vivid-cec.c
1 /*
2  * vivid-cec.c - A Virtual Video Test Driver, cec emulation
3  *
4  * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5  *
6  * This program is free software; you may redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
14  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
15  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17  * SOFTWARE.
18  */
19
20 #include <media/cec.h>
21
22 #include "vivid-core.h"
23 #include "vivid-cec.h"
24
25 #define CEC_TIM_START_BIT_TOTAL         4500
26 #define CEC_TIM_START_BIT_LOW           3700
27 #define CEC_TIM_START_BIT_HIGH          800
28 #define CEC_TIM_DATA_BIT_TOTAL          2400
29 #define CEC_TIM_DATA_BIT_0_LOW          1500
30 #define CEC_TIM_DATA_BIT_0_HIGH         900
31 #define CEC_TIM_DATA_BIT_1_LOW          600
32 #define CEC_TIM_DATA_BIT_1_HIGH         1800
33
34 void vivid_cec_bus_free_work(struct vivid_dev *dev)
35 {
36         spin_lock(&dev->cec_slock);
37         while (!list_empty(&dev->cec_work_list)) {
38                 struct vivid_cec_work *cw =
39                         list_first_entry(&dev->cec_work_list,
40                                          struct vivid_cec_work, list);
41
42                 spin_unlock(&dev->cec_slock);
43                 cancel_delayed_work_sync(&cw->work);
44                 spin_lock(&dev->cec_slock);
45                 list_del(&cw->list);
46                 cec_transmit_attempt_done(cw->adap, CEC_TX_STATUS_LOW_DRIVE);
47                 kfree(cw);
48         }
49         spin_unlock(&dev->cec_slock);
50 }
51
52 static bool vivid_cec_find_dest_adap(struct vivid_dev *dev,
53                                      struct cec_adapter *adap, u8 dest)
54 {
55         unsigned int i;
56
57         if (dest >= 0xf)
58                 return false;
59
60         if (adap != dev->cec_rx_adap && dev->cec_rx_adap &&
61             dev->cec_rx_adap->is_configured &&
62             cec_has_log_addr(dev->cec_rx_adap, dest))
63                 return true;
64
65         for (i = 0; i < MAX_OUTPUTS && dev->cec_tx_adap[i]; i++) {
66                 if (adap == dev->cec_tx_adap[i])
67                         continue;
68                 if (!dev->cec_tx_adap[i]->is_configured)
69                         continue;
70                 if (cec_has_log_addr(dev->cec_tx_adap[i], dest))
71                         return true;
72         }
73         return false;
74 }
75
76 static void vivid_cec_pin_adap_events(struct cec_adapter *adap, ktime_t ts,
77                                       const struct cec_msg *msg, bool nacked)
78 {
79         unsigned int len = nacked ? 1 : msg->len;
80         unsigned int i;
81         bool bit;
82
83         if (adap == NULL)
84                 return;
85         ts = ktime_sub_us(ts, (CEC_TIM_START_BIT_TOTAL +
86                                len * 10 * CEC_TIM_DATA_BIT_TOTAL));
87         cec_queue_pin_cec_event(adap, false, ts);
88         ts = ktime_add_us(ts, CEC_TIM_START_BIT_LOW);
89         cec_queue_pin_cec_event(adap, true, ts);
90         ts = ktime_add_us(ts, CEC_TIM_START_BIT_HIGH);
91
92         for (i = 0; i < 10 * len; i++) {
93                 switch (i % 10) {
94                 case 0 ... 7:
95                         bit = msg->msg[i / 10] & (0x80 >> (i % 10));
96                         break;
97                 case 8: /* EOM */
98                         bit = i / 10 == msg->len - 1;
99                         break;
100                 case 9: /* ACK */
101                         bit = cec_msg_is_broadcast(msg) ^ nacked;
102                         break;
103                 }
104                 cec_queue_pin_cec_event(adap, false, ts);
105                 if (bit)
106                         ts = ktime_add_us(ts, CEC_TIM_DATA_BIT_1_LOW);
107                 else
108                         ts = ktime_add_us(ts, CEC_TIM_DATA_BIT_0_LOW);
109                 cec_queue_pin_cec_event(adap, true, ts);
110                 if (bit)
111                         ts = ktime_add_us(ts, CEC_TIM_DATA_BIT_1_HIGH);
112                 else
113                         ts = ktime_add_us(ts, CEC_TIM_DATA_BIT_0_HIGH);
114         }
115 }
116
117 static void vivid_cec_pin_events(struct vivid_dev *dev,
118                                  const struct cec_msg *msg, bool nacked)
119 {
120         ktime_t ts = ktime_get();
121         unsigned int i;
122
123         vivid_cec_pin_adap_events(dev->cec_rx_adap, ts, msg, nacked);
124         for (i = 0; i < MAX_OUTPUTS; i++)
125                 vivid_cec_pin_adap_events(dev->cec_tx_adap[i], ts, msg, nacked);
126 }
127
128 static void vivid_cec_xfer_done_worker(struct work_struct *work)
129 {
130         struct vivid_cec_work *cw =
131                 container_of(work, struct vivid_cec_work, work.work);
132         struct vivid_dev *dev = cw->dev;
133         struct cec_adapter *adap = cw->adap;
134         u8 dest = cec_msg_destination(&cw->msg);
135         bool valid_dest;
136         unsigned int i;
137
138         valid_dest = cec_msg_is_broadcast(&cw->msg);
139         if (!valid_dest)
140                 valid_dest = vivid_cec_find_dest_adap(dev, adap, dest);
141
142         cw->tx_status = valid_dest ? CEC_TX_STATUS_OK : CEC_TX_STATUS_NACK;
143         spin_lock(&dev->cec_slock);
144         dev->cec_xfer_time_jiffies = 0;
145         dev->cec_xfer_start_jiffies = 0;
146         list_del(&cw->list);
147         spin_unlock(&dev->cec_slock);
148         vivid_cec_pin_events(dev, &cw->msg, !valid_dest);
149         cec_transmit_attempt_done(cw->adap, cw->tx_status);
150
151         /* Broadcast message */
152         if (adap != dev->cec_rx_adap)
153                 cec_received_msg(dev->cec_rx_adap, &cw->msg);
154         for (i = 0; i < MAX_OUTPUTS && dev->cec_tx_adap[i]; i++)
155                 if (adap != dev->cec_tx_adap[i])
156                         cec_received_msg(dev->cec_tx_adap[i], &cw->msg);
157         kfree(cw);
158 }
159
160 static void vivid_cec_xfer_try_worker(struct work_struct *work)
161 {
162         struct vivid_cec_work *cw =
163                 container_of(work, struct vivid_cec_work, work.work);
164         struct vivid_dev *dev = cw->dev;
165
166         spin_lock(&dev->cec_slock);
167         if (dev->cec_xfer_time_jiffies) {
168                 list_del(&cw->list);
169                 spin_unlock(&dev->cec_slock);
170                 cec_transmit_attempt_done(cw->adap, CEC_TX_STATUS_ARB_LOST);
171                 kfree(cw);
172         } else {
173                 INIT_DELAYED_WORK(&cw->work, vivid_cec_xfer_done_worker);
174                 dev->cec_xfer_start_jiffies = jiffies;
175                 dev->cec_xfer_time_jiffies = usecs_to_jiffies(cw->usecs);
176                 spin_unlock(&dev->cec_slock);
177                 schedule_delayed_work(&cw->work, dev->cec_xfer_time_jiffies);
178         }
179 }
180
181 static int vivid_cec_adap_enable(struct cec_adapter *adap, bool enable)
182 {
183         adap->cec_pin_is_high = true;
184         return 0;
185 }
186
187 static int vivid_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
188 {
189         return 0;
190 }
191
192 /*
193  * One data bit takes 2400 us, each byte needs 10 bits so that's 24000 us
194  * per byte.
195  */
196 #define USECS_PER_BYTE 24000
197
198 static int vivid_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
199                                    u32 signal_free_time, struct cec_msg *msg)
200 {
201         struct vivid_dev *dev = cec_get_drvdata(adap);
202         struct vivid_cec_work *cw = kzalloc(sizeof(*cw), GFP_KERNEL);
203         long delta_jiffies = 0;
204
205         if (cw == NULL)
206                 return -ENOMEM;
207         cw->dev = dev;
208         cw->adap = adap;
209         cw->usecs = CEC_FREE_TIME_TO_USEC(signal_free_time) +
210                     msg->len * USECS_PER_BYTE;
211         cw->msg = *msg;
212
213         spin_lock(&dev->cec_slock);
214         list_add(&cw->list, &dev->cec_work_list);
215         if (dev->cec_xfer_time_jiffies == 0) {
216                 INIT_DELAYED_WORK(&cw->work, vivid_cec_xfer_done_worker);
217                 dev->cec_xfer_start_jiffies = jiffies;
218                 dev->cec_xfer_time_jiffies = usecs_to_jiffies(cw->usecs);
219                 delta_jiffies = dev->cec_xfer_time_jiffies;
220         } else {
221                 INIT_DELAYED_WORK(&cw->work, vivid_cec_xfer_try_worker);
222                 delta_jiffies = dev->cec_xfer_start_jiffies +
223                         dev->cec_xfer_time_jiffies - jiffies;
224         }
225         spin_unlock(&dev->cec_slock);
226         schedule_delayed_work(&cw->work, delta_jiffies < 0 ? 0 : delta_jiffies);
227         return 0;
228 }
229
230 static int vivid_received(struct cec_adapter *adap, struct cec_msg *msg)
231 {
232         struct vivid_dev *dev = cec_get_drvdata(adap);
233         struct cec_msg reply;
234         u8 dest = cec_msg_destination(msg);
235         u8 disp_ctl;
236         char osd[14];
237
238         if (cec_msg_is_broadcast(msg))
239                 dest = adap->log_addrs.log_addr[0];
240         cec_msg_init(&reply, dest, cec_msg_initiator(msg));
241
242         switch (cec_msg_opcode(msg)) {
243         case CEC_MSG_SET_OSD_STRING:
244                 if (!cec_is_sink(adap))
245                         return -ENOMSG;
246                 cec_ops_set_osd_string(msg, &disp_ctl, osd);
247                 switch (disp_ctl) {
248                 case CEC_OP_DISP_CTL_DEFAULT:
249                         strcpy(dev->osd, osd);
250                         dev->osd_jiffies = jiffies;
251                         break;
252                 case CEC_OP_DISP_CTL_UNTIL_CLEARED:
253                         strcpy(dev->osd, osd);
254                         dev->osd_jiffies = 0;
255                         break;
256                 case CEC_OP_DISP_CTL_CLEAR:
257                         dev->osd[0] = 0;
258                         dev->osd_jiffies = 0;
259                         break;
260                 default:
261                         cec_msg_feature_abort(&reply, cec_msg_opcode(msg),
262                                               CEC_OP_ABORT_INVALID_OP);
263                         cec_transmit_msg(adap, &reply, false);
264                         break;
265                 }
266                 break;
267         default:
268                 return -ENOMSG;
269         }
270         return 0;
271 }
272
273 static const struct cec_adap_ops vivid_cec_adap_ops = {
274         .adap_enable = vivid_cec_adap_enable,
275         .adap_log_addr = vivid_cec_adap_log_addr,
276         .adap_transmit = vivid_cec_adap_transmit,
277         .received = vivid_received,
278 };
279
280 struct cec_adapter *vivid_cec_alloc_adap(struct vivid_dev *dev,
281                                          unsigned int idx,
282                                          bool is_source)
283 {
284         char name[sizeof(dev->vid_out_dev.name) + 2];
285         u32 caps = CEC_CAP_DEFAULTS | CEC_CAP_MONITOR_ALL | CEC_CAP_MONITOR_PIN;
286
287         snprintf(name, sizeof(name), "%s%d",
288                  is_source ? dev->vid_out_dev.name : dev->vid_cap_dev.name,
289                  idx);
290         return cec_allocate_adapter(&vivid_cec_adap_ops, dev,
291                 name, caps, 1);
292 }