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