253 lines · c
1/* SPDX-License-Identifier: GPL-2.0-only */2/*3 * cec-pin-priv.h - internal cec-pin header4 *5 * Copyright 2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved.6 */7 8#ifndef LINUX_CEC_PIN_PRIV_H9#define LINUX_CEC_PIN_PRIV_H10 11#include <linux/types.h>12#include <linux/atomic.h>13#include <media/cec-pin.h>14 15#define call_pin_op(pin, op, arg...) \16 ((pin && pin->ops->op && !pin->adap->devnode.unregistered) ? \17 pin->ops->op(pin->adap, ## arg) : 0)18 19#define call_void_pin_op(pin, op, arg...) \20 do { \21 if (pin && pin->ops->op && \22 !pin->adap->devnode.unregistered) \23 pin->ops->op(pin->adap, ## arg); \24 } while (0)25 26enum cec_pin_state {27 /* CEC is off */28 CEC_ST_OFF,29 /* CEC is idle, waiting for Rx or Tx */30 CEC_ST_IDLE,31 32 /* Tx states */33 34 /* Pending Tx, waiting for Signal Free Time to expire */35 CEC_ST_TX_WAIT,36 /* Low-drive was detected, wait for bus to go high */37 CEC_ST_TX_WAIT_FOR_HIGH,38 /* Drive CEC low for the start bit */39 CEC_ST_TX_START_BIT_LOW,40 /* Drive CEC high for the start bit */41 CEC_ST_TX_START_BIT_HIGH,42 /* Generate a start bit period that is too short */43 CEC_ST_TX_START_BIT_HIGH_SHORT,44 /* Generate a start bit period that is too long */45 CEC_ST_TX_START_BIT_HIGH_LONG,46 /* Drive CEC low for the start bit using the custom timing */47 CEC_ST_TX_START_BIT_LOW_CUSTOM,48 /* Drive CEC high for the start bit using the custom timing */49 CEC_ST_TX_START_BIT_HIGH_CUSTOM,50 /* Drive CEC low for the 0 bit */51 CEC_ST_TX_DATA_BIT_0_LOW,52 /* Drive CEC high for the 0 bit */53 CEC_ST_TX_DATA_BIT_0_HIGH,54 /* Generate a bit period that is too short */55 CEC_ST_TX_DATA_BIT_0_HIGH_SHORT,56 /* Generate a bit period that is too long */57 CEC_ST_TX_DATA_BIT_0_HIGH_LONG,58 /* Drive CEC low for the 1 bit */59 CEC_ST_TX_DATA_BIT_1_LOW,60 /* Drive CEC high for the 1 bit */61 CEC_ST_TX_DATA_BIT_1_HIGH,62 /* Generate a bit period that is too short */63 CEC_ST_TX_DATA_BIT_1_HIGH_SHORT,64 /* Generate a bit period that is too long */65 CEC_ST_TX_DATA_BIT_1_HIGH_LONG,66 /*67 * Wait for start of sample time to check for Ack bit or first68 * four initiator bits to check for Arbitration Lost.69 */70 CEC_ST_TX_DATA_BIT_1_HIGH_PRE_SAMPLE,71 /* Wait for end of bit period after sampling */72 CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE,73 /* Generate a bit period that is too short */74 CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE_SHORT,75 /* Generate a bit period that is too long */76 CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE_LONG,77 /* Drive CEC low for a data bit using the custom timing */78 CEC_ST_TX_DATA_BIT_LOW_CUSTOM,79 /* Drive CEC high for a data bit using the custom timing */80 CEC_ST_TX_DATA_BIT_HIGH_CUSTOM,81 /* Drive CEC low for a standalone pulse using the custom timing */82 CEC_ST_TX_PULSE_LOW_CUSTOM,83 /* Drive CEC high for a standalone pulse using the custom timing */84 CEC_ST_TX_PULSE_HIGH_CUSTOM,85 /* Start low drive */86 CEC_ST_TX_LOW_DRIVE,87 88 /* Rx states */89 90 /* Start bit low detected */91 CEC_ST_RX_START_BIT_LOW,92 /* Start bit high detected */93 CEC_ST_RX_START_BIT_HIGH,94 /* Wait for bit sample time */95 CEC_ST_RX_DATA_SAMPLE,96 /* Wait for earliest end of bit period after sampling */97 CEC_ST_RX_DATA_POST_SAMPLE,98 /* Wait for CEC to go low (i.e. end of bit period) */99 CEC_ST_RX_DATA_WAIT_FOR_LOW,100 /* Drive CEC low to send 0 Ack bit */101 CEC_ST_RX_ACK_LOW,102 /* End of 0 Ack time, wait for earliest end of bit period */103 CEC_ST_RX_ACK_LOW_POST,104 /* Wait for CEC to go high (i.e. end of bit period */105 CEC_ST_RX_ACK_HIGH_POST,106 /* Wait for earliest end of bit period and end of message */107 CEC_ST_RX_ACK_FINISH,108 /* Start low drive */109 CEC_ST_RX_LOW_DRIVE,110 111 /* Monitor pin using interrupts */112 CEC_ST_RX_IRQ,113 114 /* Total number of pin states */115 CEC_PIN_STATES116};117 118/* Error Injection */119 120/* Error injection modes */121#define CEC_ERROR_INJ_MODE_OFF 0122#define CEC_ERROR_INJ_MODE_ONCE 1123#define CEC_ERROR_INJ_MODE_ALWAYS 2124#define CEC_ERROR_INJ_MODE_TOGGLE 3125#define CEC_ERROR_INJ_MODE_MASK 3ULL126 127/* Receive error injection options */128#define CEC_ERROR_INJ_RX_NACK_OFFSET 0129#define CEC_ERROR_INJ_RX_LOW_DRIVE_OFFSET 2130#define CEC_ERROR_INJ_RX_ADD_BYTE_OFFSET 4131#define CEC_ERROR_INJ_RX_REMOVE_BYTE_OFFSET 6132#define CEC_ERROR_INJ_RX_ARB_LOST_OFFSET 8133#define CEC_ERROR_INJ_RX_MASK 0xffffULL134 135/* Transmit error injection options */136#define CEC_ERROR_INJ_TX_NO_EOM_OFFSET 16137#define CEC_ERROR_INJ_TX_EARLY_EOM_OFFSET 18138#define CEC_ERROR_INJ_TX_SHORT_BIT_OFFSET 20139#define CEC_ERROR_INJ_TX_LONG_BIT_OFFSET 22140#define CEC_ERROR_INJ_TX_CUSTOM_BIT_OFFSET 24141#define CEC_ERROR_INJ_TX_SHORT_START_OFFSET 26142#define CEC_ERROR_INJ_TX_LONG_START_OFFSET 28143#define CEC_ERROR_INJ_TX_CUSTOM_START_OFFSET 30144#define CEC_ERROR_INJ_TX_LAST_BIT_OFFSET 32145#define CEC_ERROR_INJ_TX_ADD_BYTES_OFFSET 34146#define CEC_ERROR_INJ_TX_REMOVE_BYTE_OFFSET 36147#define CEC_ERROR_INJ_TX_LOW_DRIVE_OFFSET 38148#define CEC_ERROR_INJ_TX_MASK 0xffffffffffff0000ULL149 150#define CEC_ERROR_INJ_RX_LOW_DRIVE_ARG_IDX 0151#define CEC_ERROR_INJ_RX_ARB_LOST_ARG_IDX 1152 153#define CEC_ERROR_INJ_TX_ADD_BYTES_ARG_IDX 2154#define CEC_ERROR_INJ_TX_SHORT_BIT_ARG_IDX 3155#define CEC_ERROR_INJ_TX_LONG_BIT_ARG_IDX 4156#define CEC_ERROR_INJ_TX_CUSTOM_BIT_ARG_IDX 5157#define CEC_ERROR_INJ_TX_LAST_BIT_ARG_IDX 6158#define CEC_ERROR_INJ_TX_LOW_DRIVE_ARG_IDX 7159#define CEC_ERROR_INJ_NUM_ARGS 8160 161/* Special CEC op values */162#define CEC_ERROR_INJ_OP_ANY 0x00000100163 164/* The default for the low/high time of the custom pulse */165#define CEC_TIM_CUSTOM_DEFAULT 1000166 167#define CEC_NUM_PIN_EVENTS 128168#define CEC_PIN_EVENT_FL_IS_HIGH (1 << 0)169#define CEC_PIN_EVENT_FL_DROPPED (1 << 1)170 171#define CEC_PIN_IRQ_UNCHANGED 0172#define CEC_PIN_IRQ_DISABLE 1173#define CEC_PIN_IRQ_ENABLE 2174 175struct cec_pin {176 struct cec_adapter *adap;177 const struct cec_pin_ops *ops;178 struct task_struct *kthread;179 wait_queue_head_t kthread_waitq;180 struct hrtimer timer;181 ktime_t ts;182 unsigned int wait_usecs;183 u16 la_mask;184 bool monitor_all;185 bool rx_eom;186 bool enabled_irq;187 bool enable_irq_failed;188 enum cec_pin_state state;189 struct cec_msg tx_msg;190 u32 tx_bit;191 bool tx_nacked;192 u32 tx_signal_free_time;193 bool tx_toggle;194 struct cec_msg rx_msg;195 u32 rx_bit;196 bool rx_toggle;197 u32 rx_start_bit_low_too_short_cnt;198 u64 rx_start_bit_low_too_short_ts;199 u32 rx_start_bit_low_too_short_delta;200 u32 rx_start_bit_too_short_cnt;201 u64 rx_start_bit_too_short_ts;202 u32 rx_start_bit_too_short_delta;203 u32 rx_start_bit_too_long_cnt;204 u32 rx_data_bit_too_short_cnt;205 u64 rx_data_bit_too_short_ts;206 u32 rx_data_bit_too_short_delta;207 u32 rx_data_bit_too_long_cnt;208 u32 rx_low_drive_cnt;209 210 struct cec_msg work_rx_msg;211 u8 work_tx_status;212 ktime_t work_tx_ts;213 atomic_t work_irq_change;214 atomic_t work_pin_num_events;215 unsigned int work_pin_events_wr;216 unsigned int work_pin_events_rd;217 ktime_t work_pin_ts[CEC_NUM_PIN_EVENTS];218 u8 work_pin_events[CEC_NUM_PIN_EVENTS];219 bool work_pin_events_dropped;220 u32 work_pin_events_dropped_cnt;221 ktime_t timer_ts;222 u32 timer_cnt;223 u32 timer_100us_overruns;224 u32 timer_300us_overruns;225 u32 timer_max_overrun;226 u32 timer_sum_overrun;227 228 u32 tx_custom_low_usecs;229 u32 tx_custom_high_usecs;230 bool tx_ignore_nack_until_eom;231 bool tx_custom_pulse;232 bool tx_generated_poll;233 bool tx_post_eom;234 u8 tx_extra_bytes;235 u32 tx_low_drive_cnt;236#ifdef CONFIG_CEC_PIN_ERROR_INJ237 u64 error_inj[CEC_ERROR_INJ_OP_ANY + 1];238 u8 error_inj_args[CEC_ERROR_INJ_OP_ANY + 1][CEC_ERROR_INJ_NUM_ARGS];239#endif240};241 242void cec_pin_start_timer(struct cec_pin *pin);243 244#ifdef CONFIG_CEC_PIN_ERROR_INJ245bool cec_pin_error_inj_parse_line(struct cec_adapter *adap, char *line);246int cec_pin_error_inj_show(struct cec_adapter *adap, struct seq_file *sf);247 248u16 cec_pin_rx_error_inj(struct cec_pin *pin);249u16 cec_pin_tx_error_inj(struct cec_pin *pin);250#endif251 252#endif253