/* SPDX-License-Identifier: GPL-2.0-only */ 
 | 
/* 
 | 
 * cec-pin-priv.h - internal cec-pin header 
 | 
 * 
 | 
 * Copyright 2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved. 
 | 
 */ 
 | 
  
 | 
#ifndef LINUX_CEC_PIN_PRIV_H 
 | 
#define LINUX_CEC_PIN_PRIV_H 
 | 
  
 | 
#include <linux/types.h> 
 | 
#include <linux/atomic.h> 
 | 
#include <media/cec-pin.h> 
 | 
  
 | 
enum cec_pin_state { 
 | 
    /* CEC is off */ 
 | 
    CEC_ST_OFF, 
 | 
    /* CEC is idle, waiting for Rx or Tx */ 
 | 
    CEC_ST_IDLE, 
 | 
  
 | 
    /* Tx states */ 
 | 
  
 | 
    /* Pending Tx, waiting for Signal Free Time to expire */ 
 | 
    CEC_ST_TX_WAIT, 
 | 
    /* Low-drive was detected, wait for bus to go high */ 
 | 
    CEC_ST_TX_WAIT_FOR_HIGH, 
 | 
    /* Drive CEC low for the start bit */ 
 | 
    CEC_ST_TX_START_BIT_LOW, 
 | 
    /* Drive CEC high for the start bit */ 
 | 
    CEC_ST_TX_START_BIT_HIGH, 
 | 
    /* Generate a start bit period that is too short */ 
 | 
    CEC_ST_TX_START_BIT_HIGH_SHORT, 
 | 
    /* Generate a start bit period that is too long */ 
 | 
    CEC_ST_TX_START_BIT_HIGH_LONG, 
 | 
    /* Drive CEC low for the start bit using the custom timing */ 
 | 
    CEC_ST_TX_START_BIT_LOW_CUSTOM, 
 | 
    /* Drive CEC high for the start bit using the custom timing */ 
 | 
    CEC_ST_TX_START_BIT_HIGH_CUSTOM, 
 | 
    /* Drive CEC low for the 0 bit */ 
 | 
    CEC_ST_TX_DATA_BIT_0_LOW, 
 | 
    /* Drive CEC high for the 0 bit */ 
 | 
    CEC_ST_TX_DATA_BIT_0_HIGH, 
 | 
    /* Generate a bit period that is too short */ 
 | 
    CEC_ST_TX_DATA_BIT_0_HIGH_SHORT, 
 | 
    /* Generate a bit period that is too long */ 
 | 
    CEC_ST_TX_DATA_BIT_0_HIGH_LONG, 
 | 
    /* Drive CEC low for the 1 bit */ 
 | 
    CEC_ST_TX_DATA_BIT_1_LOW, 
 | 
    /* Drive CEC high for the 1 bit */ 
 | 
    CEC_ST_TX_DATA_BIT_1_HIGH, 
 | 
    /* Generate a bit period that is too short */ 
 | 
    CEC_ST_TX_DATA_BIT_1_HIGH_SHORT, 
 | 
    /* Generate a bit period that is too long */ 
 | 
    CEC_ST_TX_DATA_BIT_1_HIGH_LONG, 
 | 
    /* 
 | 
     * Wait for start of sample time to check for Ack bit or first 
 | 
     * four initiator bits to check for Arbitration Lost. 
 | 
     */ 
 | 
    CEC_ST_TX_DATA_BIT_1_HIGH_PRE_SAMPLE, 
 | 
    /* Wait for end of bit period after sampling */ 
 | 
    CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE, 
 | 
    /* Generate a bit period that is too short */ 
 | 
    CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE_SHORT, 
 | 
    /* Generate a bit period that is too long */ 
 | 
    CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE_LONG, 
 | 
    /* Drive CEC low for a data bit using the custom timing */ 
 | 
    CEC_ST_TX_DATA_BIT_LOW_CUSTOM, 
 | 
    /* Drive CEC high for a data bit using the custom timing */ 
 | 
    CEC_ST_TX_DATA_BIT_HIGH_CUSTOM, 
 | 
    /* Drive CEC low for a standalone pulse using the custom timing */ 
 | 
    CEC_ST_TX_PULSE_LOW_CUSTOM, 
 | 
    /* Drive CEC high for a standalone pulse using the custom timing */ 
 | 
    CEC_ST_TX_PULSE_HIGH_CUSTOM, 
 | 
    /* Start low drive */ 
 | 
    CEC_ST_TX_LOW_DRIVE, 
 | 
  
 | 
    /* Rx states */ 
 | 
  
 | 
    /* Start bit low detected */ 
 | 
    CEC_ST_RX_START_BIT_LOW, 
 | 
    /* Start bit high detected */ 
 | 
    CEC_ST_RX_START_BIT_HIGH, 
 | 
    /* Wait for bit sample time */ 
 | 
    CEC_ST_RX_DATA_SAMPLE, 
 | 
    /* Wait for earliest end of bit period after sampling */ 
 | 
    CEC_ST_RX_DATA_POST_SAMPLE, 
 | 
    /* Wait for CEC to go low (i.e. end of bit period) */ 
 | 
    CEC_ST_RX_DATA_WAIT_FOR_LOW, 
 | 
    /* Drive CEC low to send 0 Ack bit */ 
 | 
    CEC_ST_RX_ACK_LOW, 
 | 
    /* End of 0 Ack time, wait for earliest end of bit period */ 
 | 
    CEC_ST_RX_ACK_LOW_POST, 
 | 
    /* Wait for CEC to go high (i.e. end of bit period */ 
 | 
    CEC_ST_RX_ACK_HIGH_POST, 
 | 
    /* Wait for earliest end of bit period and end of message */ 
 | 
    CEC_ST_RX_ACK_FINISH, 
 | 
    /* Start low drive */ 
 | 
    CEC_ST_RX_LOW_DRIVE, 
 | 
  
 | 
    /* Monitor pin using interrupts */ 
 | 
    CEC_ST_RX_IRQ, 
 | 
  
 | 
    /* Total number of pin states */ 
 | 
    CEC_PIN_STATES 
 | 
}; 
 | 
  
 | 
/* Error Injection */ 
 | 
  
 | 
/* Error injection modes */ 
 | 
#define CEC_ERROR_INJ_MODE_OFF                0 
 | 
#define CEC_ERROR_INJ_MODE_ONCE                1 
 | 
#define CEC_ERROR_INJ_MODE_ALWAYS            2 
 | 
#define CEC_ERROR_INJ_MODE_TOGGLE            3 
 | 
#define CEC_ERROR_INJ_MODE_MASK                3ULL 
 | 
  
 | 
/* Receive error injection options */ 
 | 
#define CEC_ERROR_INJ_RX_NACK_OFFSET            0 
 | 
#define CEC_ERROR_INJ_RX_LOW_DRIVE_OFFSET        2 
 | 
#define CEC_ERROR_INJ_RX_ADD_BYTE_OFFSET        4 
 | 
#define CEC_ERROR_INJ_RX_REMOVE_BYTE_OFFSET        6 
 | 
#define CEC_ERROR_INJ_RX_ARB_LOST_OFFSET        8 
 | 
#define CEC_ERROR_INJ_RX_MASK                0xffffULL 
 | 
  
 | 
/* Transmit error injection options */ 
 | 
#define CEC_ERROR_INJ_TX_NO_EOM_OFFSET            16 
 | 
#define CEC_ERROR_INJ_TX_EARLY_EOM_OFFSET        18 
 | 
#define CEC_ERROR_INJ_TX_SHORT_BIT_OFFSET        20 
 | 
#define CEC_ERROR_INJ_TX_LONG_BIT_OFFSET        22 
 | 
#define CEC_ERROR_INJ_TX_CUSTOM_BIT_OFFSET        24 
 | 
#define CEC_ERROR_INJ_TX_SHORT_START_OFFSET        26 
 | 
#define CEC_ERROR_INJ_TX_LONG_START_OFFSET        28 
 | 
#define CEC_ERROR_INJ_TX_CUSTOM_START_OFFSET        30 
 | 
#define CEC_ERROR_INJ_TX_LAST_BIT_OFFSET        32 
 | 
#define CEC_ERROR_INJ_TX_ADD_BYTES_OFFSET        34 
 | 
#define CEC_ERROR_INJ_TX_REMOVE_BYTE_OFFSET        36 
 | 
#define CEC_ERROR_INJ_TX_LOW_DRIVE_OFFSET        38 
 | 
#define CEC_ERROR_INJ_TX_MASK                0xffffffffffff0000ULL 
 | 
  
 | 
#define CEC_ERROR_INJ_RX_LOW_DRIVE_ARG_IDX        0 
 | 
#define CEC_ERROR_INJ_RX_ARB_LOST_ARG_IDX        1 
 | 
  
 | 
#define CEC_ERROR_INJ_TX_ADD_BYTES_ARG_IDX        2 
 | 
#define CEC_ERROR_INJ_TX_SHORT_BIT_ARG_IDX        3 
 | 
#define CEC_ERROR_INJ_TX_LONG_BIT_ARG_IDX        4 
 | 
#define CEC_ERROR_INJ_TX_CUSTOM_BIT_ARG_IDX        5 
 | 
#define CEC_ERROR_INJ_TX_LAST_BIT_ARG_IDX        6 
 | 
#define CEC_ERROR_INJ_TX_LOW_DRIVE_ARG_IDX        7 
 | 
#define CEC_ERROR_INJ_NUM_ARGS                8 
 | 
  
 | 
/* Special CEC op values */ 
 | 
#define CEC_ERROR_INJ_OP_ANY                0x00000100 
 | 
  
 | 
/* The default for the low/high time of the custom pulse */ 
 | 
#define CEC_TIM_CUSTOM_DEFAULT                1000 
 | 
  
 | 
#define CEC_NUM_PIN_EVENTS                128 
 | 
#define CEC_PIN_EVENT_FL_IS_HIGH            (1 << 0) 
 | 
#define CEC_PIN_EVENT_FL_DROPPED            (1 << 1) 
 | 
  
 | 
#define CEC_PIN_IRQ_UNCHANGED    0 
 | 
#define CEC_PIN_IRQ_DISABLE    1 
 | 
#define CEC_PIN_IRQ_ENABLE    2 
 | 
  
 | 
struct cec_pin { 
 | 
    struct cec_adapter        *adap; 
 | 
    const struct cec_pin_ops    *ops; 
 | 
    struct task_struct        *kthread; 
 | 
    wait_queue_head_t        kthread_waitq; 
 | 
    struct hrtimer            timer; 
 | 
    ktime_t                ts; 
 | 
    unsigned int            wait_usecs; 
 | 
    u16                la_mask; 
 | 
    bool                enabled; 
 | 
    bool                monitor_all; 
 | 
    bool                rx_eom; 
 | 
    bool                enable_irq_failed; 
 | 
    enum cec_pin_state        state; 
 | 
    struct cec_msg            tx_msg; 
 | 
    u32                tx_bit; 
 | 
    bool                tx_nacked; 
 | 
    u32                tx_signal_free_time; 
 | 
    bool                tx_toggle; 
 | 
    struct cec_msg            rx_msg; 
 | 
    u32                rx_bit; 
 | 
    bool                rx_toggle; 
 | 
    u32                rx_start_bit_low_too_short_cnt; 
 | 
    u64                rx_start_bit_low_too_short_ts; 
 | 
    u32                rx_start_bit_low_too_short_delta; 
 | 
    u32                rx_start_bit_too_short_cnt; 
 | 
    u64                rx_start_bit_too_short_ts; 
 | 
    u32                rx_start_bit_too_short_delta; 
 | 
    u32                rx_start_bit_too_long_cnt; 
 | 
    u32                rx_data_bit_too_short_cnt; 
 | 
    u64                rx_data_bit_too_short_ts; 
 | 
    u32                rx_data_bit_too_short_delta; 
 | 
    u32                rx_data_bit_too_long_cnt; 
 | 
    u32                rx_low_drive_cnt; 
 | 
  
 | 
    struct cec_msg            work_rx_msg; 
 | 
    u8                work_tx_status; 
 | 
    ktime_t                work_tx_ts; 
 | 
    atomic_t            work_irq_change; 
 | 
    atomic_t            work_pin_num_events; 
 | 
    unsigned int            work_pin_events_wr; 
 | 
    unsigned int            work_pin_events_rd; 
 | 
    ktime_t                work_pin_ts[CEC_NUM_PIN_EVENTS]; 
 | 
    u8                work_pin_events[CEC_NUM_PIN_EVENTS]; 
 | 
    bool                work_pin_events_dropped; 
 | 
    u32                work_pin_events_dropped_cnt; 
 | 
    ktime_t                timer_ts; 
 | 
    u32                timer_cnt; 
 | 
    u32                timer_100ms_overruns; 
 | 
    u32                timer_300ms_overruns; 
 | 
    u32                timer_max_overrun; 
 | 
    u32                timer_sum_overrun; 
 | 
  
 | 
    u32                tx_custom_low_usecs; 
 | 
    u32                tx_custom_high_usecs; 
 | 
    bool                tx_ignore_nack_until_eom; 
 | 
    bool                tx_custom_pulse; 
 | 
    bool                tx_generated_poll; 
 | 
    bool                tx_post_eom; 
 | 
    u8                tx_extra_bytes; 
 | 
    u32                tx_low_drive_cnt; 
 | 
#ifdef CONFIG_CEC_PIN_ERROR_INJ 
 | 
    u64                error_inj[CEC_ERROR_INJ_OP_ANY + 1]; 
 | 
    u8                error_inj_args[CEC_ERROR_INJ_OP_ANY + 1][CEC_ERROR_INJ_NUM_ARGS]; 
 | 
#endif 
 | 
}; 
 | 
  
 | 
void cec_pin_start_timer(struct cec_pin *pin); 
 | 
  
 | 
#ifdef CONFIG_CEC_PIN_ERROR_INJ 
 | 
bool cec_pin_error_inj_parse_line(struct cec_adapter *adap, char *line); 
 | 
int cec_pin_error_inj_show(struct cec_adapter *adap, struct seq_file *sf); 
 | 
  
 | 
u16 cec_pin_rx_error_inj(struct cec_pin *pin); 
 | 
u16 cec_pin_tx_error_inj(struct cec_pin *pin); 
 | 
#endif 
 | 
  
 | 
#endif 
 |