diff options
Diffstat (limited to 'drivers/media/cec/core')
| -rw-r--r-- | drivers/media/cec/core/cec-adap.c | 6 | ||||
| -rw-r--r-- | drivers/media/cec/core/cec-api.c | 2 | ||||
| -rw-r--r-- | drivers/media/cec/core/cec-core.c | 7 | ||||
| -rw-r--r-- | drivers/media/cec/core/cec-notifier.c | 2 | ||||
| -rw-r--r-- | drivers/media/cec/core/cec-pin-error-inj.c | 59 | ||||
| -rw-r--r-- | drivers/media/cec/core/cec-pin-priv.h | 8 | ||||
| -rw-r--r-- | drivers/media/cec/core/cec-pin.c | 33 |
7 files changed, 106 insertions, 11 deletions
diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c index ba6828ef540e..8f7244ac1d43 100644 --- a/drivers/media/cec/core/cec-adap.c +++ b/drivers/media/cec/core/cec-adap.c @@ -95,7 +95,7 @@ void cec_queue_event_fh(struct cec_fh *fh, if (ev_idx < CEC_NUM_CORE_EVENTS) entry = &fh->core_events[ev_idx]; else - entry = kmalloc(sizeof(*entry), GFP_KERNEL); + entry = kmalloc_obj(*entry); if (entry) { if (new_ev->event == CEC_EVENT_LOST_MSGS && fh->queued_events[ev_idx]) { @@ -218,7 +218,7 @@ static void cec_queue_msg_fh(struct cec_fh *fh, const struct cec_msg *msg) struct cec_msg_entry *entry; mutex_lock(&fh->lock); - entry = kmalloc(sizeof(*entry), GFP_KERNEL); + entry = kmalloc_obj(*entry); if (entry) { entry->msg = *msg; /* Add new msg at the end of the queue */ @@ -922,7 +922,7 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, return -EBUSY; } - data = kzalloc(sizeof(*data), GFP_KERNEL); + data = kzalloc_obj(*data); if (!data) return -ENOMEM; diff --git a/drivers/media/cec/core/cec-api.c b/drivers/media/cec/core/cec-api.c index 2b50578d107e..103ded79526f 100644 --- a/drivers/media/cec/core/cec-api.c +++ b/drivers/media/cec/core/cec-api.c @@ -555,7 +555,7 @@ static int cec_open(struct inode *inode, struct file *filp) struct cec_devnode *devnode = container_of(inode->i_cdev, struct cec_devnode, cdev); struct cec_adapter *adap = to_cec_adapter(devnode); - struct cec_fh *fh = kzalloc(sizeof(*fh), GFP_KERNEL); + struct cec_fh *fh = kzalloc_obj(*fh); /* * Initial events that are automatically sent when the cec device is * opened. diff --git a/drivers/media/cec/core/cec-core.c b/drivers/media/cec/core/cec-core.c index e10bd588a586..0fcd3b5e60c8 100644 --- a/drivers/media/cec/core/cec-core.c +++ b/drivers/media/cec/core/cec-core.c @@ -237,7 +237,7 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, return ERR_PTR(-EINVAL); if (WARN_ON(!available_las || available_las > CEC_MAX_LOG_ADDRS)) return ERR_PTR(-EINVAL); - adap = kzalloc(sizeof(*adap), GFP_KERNEL); + adap = kzalloc_obj(*adap); if (!adap) return ERR_PTR(-ENOMEM); strscpy(adap->name, name, sizeof(adap->name)); @@ -338,8 +338,8 @@ int cec_register_adapter(struct cec_adapter *adap, res = cec_devnode_register(&adap->devnode, adap->owner); if (res) { #ifdef CONFIG_MEDIA_CEC_RC - /* Note: rc_unregister also calls rc_free */ rc_unregister_device(adap->rc); + rc_free_device(adap->rc); adap->rc = NULL; #endif return res; @@ -421,6 +421,7 @@ static int __init cec_devnode_init(void) ret = bus_register(&cec_bus_type); if (ret < 0) { + debugfs_remove_recursive(top_cec_dir); unregister_chrdev_region(cec_dev_t, CEC_NUM_DEVICES); pr_warn("cec: bus_register failed\n"); return -EIO; @@ -439,6 +440,6 @@ static void __exit cec_devnode_exit(void) subsys_initcall(cec_devnode_init); module_exit(cec_devnode_exit) -MODULE_AUTHOR("Hans Verkuil <hansverk@cisco.com>"); +MODULE_AUTHOR("Hans Verkuil <hverkuil@kernel.org>"); MODULE_DESCRIPTION("Device node registration for cec drivers"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/cec/core/cec-notifier.c b/drivers/media/cec/core/cec-notifier.c index 1fed0b1c71e9..8cf1474d0361 100644 --- a/drivers/media/cec/core/cec-notifier.c +++ b/drivers/media/cec/core/cec-notifier.c @@ -63,7 +63,7 @@ cec_notifier_get_conn(struct device *hdmi_dev, const char *port_name) return n; } } - n = kzalloc(sizeof(*n), GFP_KERNEL); + n = kzalloc_obj(*n); if (!n) goto unlock; n->hdmi_dev = hdmi_dev; diff --git a/drivers/media/cec/core/cec-pin-error-inj.c b/drivers/media/cec/core/cec-pin-error-inj.c index 6e61a04b8168..d9e613c7ce3f 100644 --- a/drivers/media/cec/core/cec-pin-error-inj.c +++ b/drivers/media/cec/core/cec-pin-error-inj.c @@ -91,16 +91,22 @@ bool cec_pin_error_inj_parse_line(struct cec_adapter *adap, char *line) if (!strcmp(token, "clear")) { memset(pin->error_inj, 0, sizeof(pin->error_inj)); pin->rx_toggle = pin->tx_toggle = false; + pin->rx_no_low_drive = false; pin->tx_ignore_nack_until_eom = false; 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")) { for (i = 0; i <= CEC_ERROR_INJ_OP_ANY; i++) pin->error_inj[i] &= ~CEC_ERROR_INJ_RX_MASK; pin->rx_toggle = false; + pin->rx_no_low_drive = false; return true; } if (!strcmp(token, "tx-clear")) { @@ -111,6 +117,14 @@ 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-no-low-drive")) { + pin->rx_no_low_drive = true; return true; } if (!strcmp(token, "tx-ignore-nack-until-eom")) { @@ -122,6 +136,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 +161,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; } @@ -273,6 +311,9 @@ int cec_pin_error_inj_show(struct cec_adapter *adap, struct seq_file *sf) seq_puts(sf, "# <op> rx-clear clear all rx error injections for <op>\n"); seq_puts(sf, "# <op> tx-clear clear all tx error injections for <op>\n"); seq_puts(sf, "#\n"); + seq_puts(sf, "# RX error injection settings:\n"); + seq_puts(sf, "# rx-no-low-drive do not generate low-drive pulses\n"); + seq_puts(sf, "#\n"); seq_puts(sf, "# RX error injection:\n"); seq_puts(sf, "# <op>[,<mode>] rx-nack NACK the message instead of sending an ACK\n"); seq_puts(sf, "# <op>[,<mode>] rx-low-drive <bit> force a low-drive condition at this bit position\n"); @@ -285,6 +326,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"); @@ -332,8 +377,14 @@ int cec_pin_error_inj_show(struct cec_adapter *adap, struct seq_file *sf) } } + if (pin->rx_no_low_drive) + seq_puts(sf, "rx-no-low-drive\n"); 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 +393,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; } diff --git a/drivers/media/cec/core/cec-pin-priv.h b/drivers/media/cec/core/cec-pin-priv.h index 156a9f81be94..e7801be9adb9 100644 --- a/drivers/media/cec/core/cec-pin-priv.h +++ b/drivers/media/cec/core/cec-pin-priv.h @@ -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) @@ -225,12 +228,17 @@ struct cec_pin { u32 timer_max_overrun; u32 timer_sum_overrun; + bool rx_no_low_drive; 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 diff --git a/drivers/media/cec/core/cec-pin.c b/drivers/media/cec/core/cec-pin.c index 59ac12113f3a..6e1c39102832 100644 --- a/drivers/media/cec/core/cec-pin.c +++ b/drivers/media/cec/core/cec-pin.c @@ -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); } @@ -770,7 +797,7 @@ static void cec_pin_rx_states(struct cec_pin *pin, ktime_t ts) * Go to low drive state when the total bit time is * too short. */ - if (delta < CEC_TIM_DATA_BIT_TOTAL_MIN) { + if (delta < CEC_TIM_DATA_BIT_TOTAL_MIN && !pin->rx_no_low_drive) { if (!pin->rx_data_bit_too_short_cnt++) { pin->rx_data_bit_too_short_ts = ktime_to_ns(pin->ts); pin->rx_data_bit_too_short_delta = delta; @@ -1340,7 +1367,7 @@ struct cec_adapter *cec_pin_allocate_adapter(const struct cec_pin_ops *pin_ops, void *priv, const char *name, u32 caps) { struct cec_adapter *adap; - struct cec_pin *pin = kzalloc(sizeof(*pin), GFP_KERNEL); + struct cec_pin *pin = kzalloc_obj(*pin); if (pin == NULL) return ERR_PTR(-ENOMEM); @@ -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, |
