summaryrefslogtreecommitdiff
path: root/drivers/media/platform/vivid/vivid-cec.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/vivid/vivid-cec.c')
-rw-r--r--drivers/media/platform/vivid/vivid-cec.c66
1 files changed, 64 insertions, 2 deletions
diff --git a/drivers/media/platform/vivid/vivid-cec.c b/drivers/media/platform/vivid/vivid-cec.c
index e15705758969..b55d278d38a7 100644
--- a/drivers/media/platform/vivid/vivid-cec.c
+++ b/drivers/media/platform/vivid/vivid-cec.c
@@ -22,6 +22,15 @@
#include "vivid-core.h"
#include "vivid-cec.h"
+#define CEC_TIM_START_BIT_TOTAL 4500
+#define CEC_TIM_START_BIT_LOW 3700
+#define CEC_TIM_START_BIT_HIGH 800
+#define CEC_TIM_DATA_BIT_TOTAL 2400
+#define CEC_TIM_DATA_BIT_0_LOW 1500
+#define CEC_TIM_DATA_BIT_0_HIGH 900
+#define CEC_TIM_DATA_BIT_1_LOW 600
+#define CEC_TIM_DATA_BIT_1_HIGH 1800
+
void vivid_cec_bus_free_work(struct vivid_dev *dev)
{
spin_lock(&dev->cec_slock);
@@ -64,6 +73,58 @@ static bool vivid_cec_find_dest_adap(struct vivid_dev *dev,
return false;
}
+static void vivid_cec_pin_adap_events(struct cec_adapter *adap, ktime_t ts,
+ const struct cec_msg *msg, bool nacked)
+{
+ unsigned int len = nacked ? 1 : msg->len;
+ unsigned int i;
+ bool bit;
+
+ if (adap == NULL)
+ return;
+ ts = ktime_sub_us(ts, (CEC_TIM_START_BIT_TOTAL +
+ len * 10 * CEC_TIM_DATA_BIT_TOTAL));
+ cec_queue_pin_cec_event(adap, false, ts);
+ ts = ktime_add_us(ts, CEC_TIM_START_BIT_LOW);
+ cec_queue_pin_cec_event(adap, true, ts);
+ ts = ktime_add_us(ts, CEC_TIM_START_BIT_HIGH);
+
+ for (i = 0; i < 10 * len; i++) {
+ switch (i % 10) {
+ case 0 ... 7:
+ bit = msg->msg[i / 10] & (0x80 >> (i % 10));
+ break;
+ case 8: /* EOM */
+ bit = i / 10 == msg->len - 1;
+ break;
+ case 9: /* ACK */
+ bit = cec_msg_is_broadcast(msg) ^ nacked;
+ break;
+ }
+ cec_queue_pin_cec_event(adap, false, ts);
+ if (bit)
+ ts = ktime_add_us(ts, CEC_TIM_DATA_BIT_1_LOW);
+ else
+ ts = ktime_add_us(ts, CEC_TIM_DATA_BIT_0_LOW);
+ cec_queue_pin_cec_event(adap, true, ts);
+ if (bit)
+ ts = ktime_add_us(ts, CEC_TIM_DATA_BIT_1_HIGH);
+ else
+ ts = ktime_add_us(ts, CEC_TIM_DATA_BIT_0_HIGH);
+ }
+}
+
+static void vivid_cec_pin_events(struct vivid_dev *dev,
+ const struct cec_msg *msg, bool nacked)
+{
+ ktime_t ts = ktime_get();
+ unsigned int i;
+
+ vivid_cec_pin_adap_events(dev->cec_rx_adap, ts, msg, nacked);
+ for (i = 0; i < MAX_OUTPUTS; i++)
+ vivid_cec_pin_adap_events(dev->cec_tx_adap[i], ts, msg, nacked);
+}
+
static void vivid_cec_xfer_done_worker(struct work_struct *work)
{
struct vivid_cec_work *cw =
@@ -84,6 +145,7 @@ static void vivid_cec_xfer_done_worker(struct work_struct *work)
dev->cec_xfer_start_jiffies = 0;
list_del(&cw->list);
spin_unlock(&dev->cec_slock);
+ vivid_cec_pin_events(dev, &cw->msg, !valid_dest);
cec_transmit_attempt_done(cw->adap, cw->tx_status);
/* Broadcast message */
@@ -118,6 +180,7 @@ static void vivid_cec_xfer_try_worker(struct work_struct *work)
static int vivid_cec_adap_enable(struct cec_adapter *adap, bool enable)
{
+ adap->cec_pin_is_high = true;
return 0;
}
@@ -219,8 +282,7 @@ struct cec_adapter *vivid_cec_alloc_adap(struct vivid_dev *dev,
bool is_source)
{
char name[sizeof(dev->vid_out_dev.name) + 2];
- u32 caps = CEC_CAP_TRANSMIT | CEC_CAP_LOG_ADDRS |
- CEC_CAP_PASSTHROUGH | CEC_CAP_RC | CEC_CAP_MONITOR_ALL;
+ u32 caps = CEC_CAP_DEFAULTS | CEC_CAP_MONITOR_ALL | CEC_CAP_MONITOR_PIN;
snprintf(name, sizeof(name), "%s%d",
is_source ? dev->vid_out_dev.name : dev->vid_cap_dev.name,