mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 00:53:34 +02:00
media: cec: core: add glitch error injection
This adds support for inserting 'glitches' after a falling and/or rising edge. This tests what happens when there are little voltage spikes after falling or rising edges, which can be caused due to noise or reflections on the CEC line. A proper CEC implementation will deglitch this, but a poor implementation can create a Low Drive pulse in response, effectively making CEC unusable. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
This commit is contained in:
parent
5bcc50cb55
commit
36e713438a
|
|
@ -95,6 +95,10 @@ bool cec_pin_error_inj_parse_line(struct cec_adapter *adap, char *line)
|
|||
pin->tx_custom_pulse = false;
|
||||
pin->tx_custom_low_usecs = CEC_TIM_CUSTOM_DEFAULT;
|
||||
pin->tx_custom_high_usecs = CEC_TIM_CUSTOM_DEFAULT;
|
||||
pin->tx_glitch_low_usecs = CEC_TIM_GLITCH_DEFAULT;
|
||||
pin->tx_glitch_high_usecs = CEC_TIM_GLITCH_DEFAULT;
|
||||
pin->tx_glitch_falling_edge = false;
|
||||
pin->tx_glitch_rising_edge = false;
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(token, "rx-clear")) {
|
||||
|
|
@ -111,6 +115,10 @@ bool cec_pin_error_inj_parse_line(struct cec_adapter *adap, char *line)
|
|||
pin->tx_custom_pulse = false;
|
||||
pin->tx_custom_low_usecs = CEC_TIM_CUSTOM_DEFAULT;
|
||||
pin->tx_custom_high_usecs = CEC_TIM_CUSTOM_DEFAULT;
|
||||
pin->tx_glitch_low_usecs = CEC_TIM_GLITCH_DEFAULT;
|
||||
pin->tx_glitch_high_usecs = CEC_TIM_GLITCH_DEFAULT;
|
||||
pin->tx_glitch_falling_edge = false;
|
||||
pin->tx_glitch_rising_edge = false;
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(token, "tx-ignore-nack-until-eom")) {
|
||||
|
|
@ -122,6 +130,14 @@ bool cec_pin_error_inj_parse_line(struct cec_adapter *adap, char *line)
|
|||
cec_pin_start_timer(pin);
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(token, "tx-glitch-falling-edge")) {
|
||||
pin->tx_glitch_falling_edge = true;
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(token, "tx-glitch-rising-edge")) {
|
||||
pin->tx_glitch_rising_edge = true;
|
||||
return true;
|
||||
}
|
||||
if (!p)
|
||||
return false;
|
||||
|
||||
|
|
@ -139,7 +155,23 @@ bool cec_pin_error_inj_parse_line(struct cec_adapter *adap, char *line)
|
|||
|
||||
if (kstrtou32(p, 0, &usecs) || usecs > 10000000)
|
||||
return false;
|
||||
pin->tx_custom_high_usecs = usecs;
|
||||
pin->tx_glitch_high_usecs = usecs;
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(token, "tx-glitch-low-usecs")) {
|
||||
u32 usecs;
|
||||
|
||||
if (kstrtou32(p, 0, &usecs) || usecs > 100)
|
||||
return false;
|
||||
pin->tx_glitch_low_usecs = usecs;
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(token, "tx-glitch-high-usecs")) {
|
||||
u32 usecs;
|
||||
|
||||
if (kstrtou32(p, 0, &usecs) || usecs > 100)
|
||||
return false;
|
||||
pin->tx_glitch_high_usecs = usecs;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -285,6 +317,10 @@ int cec_pin_error_inj_show(struct cec_adapter *adap, struct seq_file *sf)
|
|||
seq_puts(sf, "# tx-custom-low-usecs <usecs> define the 'low' time for the custom pulse\n");
|
||||
seq_puts(sf, "# tx-custom-high-usecs <usecs> define the 'high' time for the custom pulse\n");
|
||||
seq_puts(sf, "# tx-custom-pulse transmit the custom pulse once the bus is idle\n");
|
||||
seq_puts(sf, "# tx-glitch-low-usecs <usecs> define the 'low' time for the glitch pulse\n");
|
||||
seq_puts(sf, "# tx-glitch-high-usecs <usecs> define the 'high' time for the glitch pulse\n");
|
||||
seq_puts(sf, "# tx-glitch-falling-edge send the glitch pulse after every falling edge\n");
|
||||
seq_puts(sf, "# tx-glitch-rising-edge send the glitch pulse after every rising edge\n");
|
||||
seq_puts(sf, "#\n");
|
||||
seq_puts(sf, "# TX error injection:\n");
|
||||
seq_puts(sf, "# <op>[,<mode>] tx-no-eom don't set the EOM bit\n");
|
||||
|
|
@ -334,6 +370,10 @@ int cec_pin_error_inj_show(struct cec_adapter *adap, struct seq_file *sf)
|
|||
|
||||
if (pin->tx_ignore_nack_until_eom)
|
||||
seq_puts(sf, "tx-ignore-nack-until-eom\n");
|
||||
if (pin->tx_glitch_falling_edge)
|
||||
seq_puts(sf, "tx-glitch-falling-edge\n");
|
||||
if (pin->tx_glitch_rising_edge)
|
||||
seq_puts(sf, "tx-glitch-rising-edge\n");
|
||||
if (pin->tx_custom_pulse)
|
||||
seq_puts(sf, "tx-custom-pulse\n");
|
||||
if (pin->tx_custom_low_usecs != CEC_TIM_CUSTOM_DEFAULT)
|
||||
|
|
@ -342,5 +382,11 @@ int cec_pin_error_inj_show(struct cec_adapter *adap, struct seq_file *sf)
|
|||
if (pin->tx_custom_high_usecs != CEC_TIM_CUSTOM_DEFAULT)
|
||||
seq_printf(sf, "tx-custom-high-usecs %u\n",
|
||||
pin->tx_custom_high_usecs);
|
||||
if (pin->tx_glitch_low_usecs != CEC_TIM_GLITCH_DEFAULT)
|
||||
seq_printf(sf, "tx-glitch-low-usecs %u\n",
|
||||
pin->tx_glitch_low_usecs);
|
||||
if (pin->tx_glitch_high_usecs != CEC_TIM_GLITCH_DEFAULT)
|
||||
seq_printf(sf, "tx-glitch-high-usecs %u\n",
|
||||
pin->tx_glitch_high_usecs);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,6 +164,9 @@ enum cec_pin_state {
|
|||
/* The default for the low/high time of the custom pulse */
|
||||
#define CEC_TIM_CUSTOM_DEFAULT 1000
|
||||
|
||||
/* The default for the low/high time of the glitch pulse */
|
||||
#define CEC_TIM_GLITCH_DEFAULT 1
|
||||
|
||||
#define CEC_NUM_PIN_EVENTS 128
|
||||
#define CEC_PIN_EVENT_FL_IS_HIGH (1 << 0)
|
||||
#define CEC_PIN_EVENT_FL_DROPPED (1 << 1)
|
||||
|
|
@ -227,10 +230,14 @@ struct cec_pin {
|
|||
|
||||
u32 tx_custom_low_usecs;
|
||||
u32 tx_custom_high_usecs;
|
||||
u32 tx_glitch_low_usecs;
|
||||
u32 tx_glitch_high_usecs;
|
||||
bool tx_ignore_nack_until_eom;
|
||||
bool tx_custom_pulse;
|
||||
bool tx_generated_poll;
|
||||
bool tx_post_eom;
|
||||
bool tx_glitch_falling_edge;
|
||||
bool tx_glitch_rising_edge;
|
||||
u8 tx_extra_bytes;
|
||||
u32 tx_low_drive_cnt;
|
||||
#ifdef CONFIG_CEC_PIN_ERROR_INJ
|
||||
|
|
|
|||
|
|
@ -142,15 +142,42 @@ static bool cec_pin_read(struct cec_pin *pin)
|
|||
return v;
|
||||
}
|
||||
|
||||
static void cec_pin_insert_glitch(struct cec_pin *pin, bool rising_edge)
|
||||
{
|
||||
/*
|
||||
* Insert a short glitch after the falling or rising edge to
|
||||
* simulate reflections on the CEC line. This can be used to
|
||||
* test deglitch filters, which should be present in CEC devices
|
||||
* to deal with noise on the line.
|
||||
*/
|
||||
if (!pin->tx_glitch_high_usecs || !pin->tx_glitch_low_usecs)
|
||||
return;
|
||||
if (rising_edge) {
|
||||
udelay(pin->tx_glitch_high_usecs);
|
||||
call_void_pin_op(pin, low);
|
||||
udelay(pin->tx_glitch_low_usecs);
|
||||
call_void_pin_op(pin, high);
|
||||
} else {
|
||||
udelay(pin->tx_glitch_low_usecs);
|
||||
call_void_pin_op(pin, high);
|
||||
udelay(pin->tx_glitch_high_usecs);
|
||||
call_void_pin_op(pin, low);
|
||||
}
|
||||
}
|
||||
|
||||
static void cec_pin_low(struct cec_pin *pin)
|
||||
{
|
||||
call_void_pin_op(pin, low);
|
||||
if (pin->tx_glitch_falling_edge && pin->adap->cec_pin_is_high)
|
||||
cec_pin_insert_glitch(pin, false);
|
||||
cec_pin_update(pin, false, false);
|
||||
}
|
||||
|
||||
static bool cec_pin_high(struct cec_pin *pin)
|
||||
{
|
||||
call_void_pin_op(pin, high);
|
||||
if (pin->tx_glitch_rising_edge && !pin->adap->cec_pin_is_high)
|
||||
cec_pin_insert_glitch(pin, true);
|
||||
return cec_pin_read(pin);
|
||||
}
|
||||
|
||||
|
|
@ -1350,6 +1377,8 @@ struct cec_adapter *cec_pin_allocate_adapter(const struct cec_pin_ops *pin_ops,
|
|||
init_waitqueue_head(&pin->kthread_waitq);
|
||||
pin->tx_custom_low_usecs = CEC_TIM_CUSTOM_DEFAULT;
|
||||
pin->tx_custom_high_usecs = CEC_TIM_CUSTOM_DEFAULT;
|
||||
pin->tx_glitch_low_usecs = CEC_TIM_GLITCH_DEFAULT;
|
||||
pin->tx_glitch_high_usecs = CEC_TIM_GLITCH_DEFAULT;
|
||||
|
||||
adap = cec_allocate_adapter(&cec_pin_adap_ops, priv, name,
|
||||
caps | CEC_CAP_MONITOR_ALL | CEC_CAP_MONITOR_PIN,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user