Commit 4f88b0de authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

media: vivid: add CEC pin monitoring emulation

Add support to emulate CEC pin monitoring. There are few hardware devices
that support this, so being able to emulate it here helps developing
software for this.
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent 28e11b15
......@@ -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,7 +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_DEFAULTS | 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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment