// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
*/
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/sched/types.h>
#include <media/cec-pin.h>
#include "cec-pin-priv.h"
/* All timings are in microseconds */
/* start bit timings */
#define CEC_TIM_START_BIT_LOW 3700
#define CEC_TIM_START_BIT_LOW_MIN 3500
#define CEC_TIM_START_BIT_LOW_MAX 3900
#define CEC_TIM_START_BIT_TOTAL 4500
#define CEC_TIM_START_BIT_TOTAL_MIN 4300
#define CEC_TIM_START_BIT_TOTAL_MAX 4700
/* data bit timings */
#define CEC_TIM_DATA_BIT_0_LOW 1500
#define CEC_TIM_DATA_BIT_0_LOW_MIN 1300
#define CEC_TIM_DATA_BIT_0_LOW_MAX 1700
#define CEC_TIM_DATA_BIT_1_LOW 600
#define CEC_TIM_DATA_BIT_1_LOW_MIN 400
#define CEC_TIM_DATA_BIT_1_LOW_MAX 800
#define CEC_TIM_DATA_BIT_TOTAL 2400
#define CEC_TIM_DATA_BIT_TOTAL_MIN 2050
#define CEC_TIM_DATA_BIT_TOTAL_MAX 2750
/* earliest safe time to sample the bit state */
#define CEC_TIM_DATA_BIT_SAMPLE 850
/* earliest time the bit is back to 1 (T7 + 50) */
#define CEC_TIM_DATA_BIT_HIGH 1750
/* when idle, sample once per millisecond */
#define CEC_TIM_IDLE_SAMPLE 1000
/* when processing the start bit, sample twice per millisecond */
#define CEC_TIM_START_BIT_SAMPLE 500
/* when polling for a state change, sample once every 50 microseconds */
#define CEC_TIM_SAMPLE 50
#define CEC_TIM_LOW_DRIVE_ERROR (1.5 * CEC_TIM_DATA_BIT_TOTAL)
/*
* Total data bit time that is too short/long for a valid bit,
* used for error injection.
*/
#define CEC_TIM_DATA_BIT_TOTAL_SHORT 1800
#define CEC_TIM_DATA_BIT_TOTAL_LONG 2900
/*
* Total start bit time that is too short/long for a valid bit,
* used for error injection.
*/
#define CEC_TIM_START_BIT_TOTAL_SHORT 4100
#define CEC_TIM_START_BIT_TOTAL_LONG 5000
/* Data bits are 0-7, EOM is bit 8 and ACK is bit 9 */
#define EOM_BIT 8
#define ACK_BIT 9
struct cec_state {
const char * const name;
unsigned int usecs;
};
static const struct cec_state states[CEC_PIN_STATES] = {
{ "Off", 0 },
{ "Idle", CEC_TIM_IDLE_SAMPLE },
{ "Tx Wait", CEC_TIM_SAMPLE },
{ "Tx Wait for High", CEC_TIM_IDLE_SAMPLE },
{ "Tx Start Bit Low", CEC_TIM_START_BIT_LOW },
{ "Tx Start Bit High", CEC_TIM_START_BIT_TOTAL - CEC_TIM_START_BIT_LOW },
{ "Tx Start Bit High Short", CEC_TIM_START_BIT_TOTAL_SHORT - CEC_TIM_START_BIT_LOW },
{ "Tx Start Bit High Long", CEC_TIM_START_BIT_TOTAL_LONG - CEC_TIM_START_BIT_LOW },
{ "Tx Start Bit Low Custom", 0 },
{ "Tx Start Bit High Custom", 0 },
{ "Tx Data 0 Low", CEC_TIM_DATA_BIT_0_LOW },
{ "Tx Data 0 High", CEC_TIM_DATA_BIT_TOTAL - CEC_TIM_DATA_BIT_0_LOW },
{ "Tx Data 0 High Short", CEC_TIM_DATA_BIT_TOTAL_SHORT - CEC_TIM_DATA_BIT_0_LOW },
{ "Tx Data 0 High Long", CEC_TIM_DATA_BIT_TOTAL_LONG - CEC_TIM_DATA_BIT_0_LOW },
{ "Tx Data 1 Low", CEC_TIM_DATA_BIT_1_LOW },
{ "Tx Data 1 High", CEC_TIM_DATA_BIT_TOTAL - CEC_TIM_DATA_BIT_1_LOW },
{ "Tx Data 1 High Short", CEC_TIM_DATA_BIT_TOTAL_SHORT - CEC_TIM_DATA_BIT_1_LOW },
{ "Tx Data 1 High Long", CEC_TIM_DATA_BIT_TOTAL_LONG - CEC_TIM_DATA_BIT_1_LOW },
{ "Tx Data 1 High Pre Sample", CEC_TIM_DATA_BIT_SAMPLE - CEC_TIM_DATA_BIT_1_LOW },
{ "Tx Data 1 High Post Sample", CEC_TIM_DATA_BIT_TOTAL - CEC_TIM_DATA_BIT_SAMPLE },
{ "Tx Data 1 High Post Sample Short", CEC_TIM_DATA_BIT_TOTAL_SHORT - CEC_TIM_DATA_BIT_SAMPLE },
{ "Tx Data 1 High Post Sample Long", CEC_TIM_DATA_BIT_TOTAL_LONG - CEC_TIM_DATA_BIT_SAMPLE },
{ "Tx Data Bit Low Custom", 0 },
{ "Tx Data Bit High Custom", 0 },
{ "Tx Pulse Low Custom", 0 },
{ "Tx Pulse High Custom", 0 },
{ "Tx Low Drive", CEC_TIM_LOW_DRIVE_ERROR },
{ "Rx Start Bit Low", CEC_TIM_SAMPLE },
{ "Rx Start Bit High", CEC_TIM_SAMPL