724 lines
19 KiB
C
724 lines
19 KiB
C
#include "spdif/hdmi_cec.h"
|
|
#include "spdif/hdmi_cec_api.h"
|
|
#include "app_config.h"
|
|
#include "asm/clock.h"
|
|
#include "app_config.h"
|
|
#include "gpio.h"
|
|
#include "system/timer.h"
|
|
#if ((TCFG_SPDIF_ENABLE) && (TCFG_HDMI_ARC_ENABLE))
|
|
|
|
//#pragma const_seg(".HDMI_const")
|
|
//#pragma code_seg(".HDMI_code")
|
|
|
|
|
|
static void cec_set_wait_time(u32 us);
|
|
|
|
static void cec_set_line_state(const u8 state)
|
|
{
|
|
gpio_direction_output(TCFG_HDMI_CEC_PORT, state);
|
|
}
|
|
|
|
static u32 cec_get_line_state()
|
|
{
|
|
return gpio_read(TCFG_HDMI_CEC_PORT);
|
|
}
|
|
|
|
static u8 CEC_Version_cmd[3] = {0x00, CEC_VERSION, 0x04}; //0x04 :1.3a ????
|
|
static u8 Report_Power_Status_Cmd[3] = {0x00, 0x90, 0x00}; //0x00:ON ; 0x01:OFF
|
|
static u8 Standby_Cmd[2] = {0x00, STANDBY};
|
|
|
|
static u8 PollingMessage_cmd[1] = {0x55};
|
|
static u8 Report_Physical_Add_Cmd1[7] = {0x5F, REPORT_PHYSICAL_ADDRESS, 0x20, 0x00, 0x05};
|
|
static u8 Report_Physical_Add_Cmd[7] = {0x5F, REPORT_PHYSICAL_ADDRESS, 0x10, 0x00, 0x05};
|
|
|
|
static u8 Device_Vendor_Id_Cmd[5] = {0x5f, DEVICE_VENDOR_ID, 0x45, 0x58, 0x50};
|
|
static u8 Set_System_Audio_Mode_cmd[] = {0x50, SET_SYSTEM_AUDIO_MODE, 0x01};
|
|
static u8 Broadcast_System_Audio_Mode_cmd[] = {0x5F, SET_SYSTEM_AUDIO_MODE, 0x01};
|
|
static u8 Set_Osd_Name_cmd[] = {0x50, CECOP_SET_OSD_NAME, 0x41, 0x75, 0x64, 0x69, 0x6f, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d}; //["Audio System"]
|
|
|
|
static u8 System_Audio_Mode_Status_cmd[] = {0x50, CECOP_SYSTEM_AUDIO_MODE_STATUS, 0x01};
|
|
//static u8 Report_Audio_Status_cmd[] = {0x50, CECOP_REPORT_AUDIO_STATUS, 0xB2};// bit7 off/on bit6-0 volume
|
|
static u8 Report_Audio_Status_cmd[] = {0x50, CECOP_REPORT_AUDIO_STATUS, 0x32};
|
|
|
|
static u8 Report_Power_Status_cmd[] = {0x50, CECOP_REPORT_POWER_STATUS, 0x00};// 0:on 1 standby 2: S2O 3: o2s
|
|
|
|
static u8 Terminate_Arc_cmd[2] = {0x50, CECOP_ARC_TERMINATE};
|
|
static u8 Initiate_Arc_cmd[2] = {0x50, INITIATE_ARC};
|
|
static u8 Report_Short_Audio_Desc_cmd[8] = {0x50, REPORT_SHORT_AUDIO_DESCRIPTOR, 0x15, 0x17, 0x50, 0x3E, 0x06, 0xC0}; //AC-3 6Ch (48 44 32k) 640kbps/ DTS 7Ch (48 44K) 1536kbps
|
|
|
|
static u8 Give_Tuner_Device_Status_cmd[3] = {0x50, CECOP_GIVE_TUNER_DEVICE_STATUS, 0x01};
|
|
static u8 Feature_Abort_cmd[3] = {0x50, CECOP_FEATURE_ABORT, 0x00};
|
|
|
|
#define CEC_IDLE 0
|
|
#define CEC_TX 1
|
|
#define CEC_RX 2
|
|
|
|
static u8 cec_work_mode;
|
|
static s8 cec_state;
|
|
static u16 high_period_time;
|
|
enum {
|
|
CEC_SUCC,
|
|
NAK_HEAD,
|
|
NAK_DATA,
|
|
};
|
|
|
|
struct cec_msg_frame {
|
|
u8 *msg;
|
|
u8 msg_len;
|
|
u8 tx_count;
|
|
u8 ack;
|
|
u8 broadcast;
|
|
};
|
|
|
|
static struct cec_msg_frame cec_frame;
|
|
|
|
struct hdmi_arc_t {
|
|
u8 msg_count;
|
|
u8 state;
|
|
u8 logic_addr;
|
|
u8 rx_count;
|
|
u8 rx_msg;
|
|
u8 idle_time;
|
|
u16 time_id;
|
|
u8 cec_ok;
|
|
|
|
u8 msg[17];
|
|
|
|
};
|
|
|
|
static struct hdmi_arc_t arc_devcie;
|
|
#define __this (&arc_devcie)
|
|
|
|
typedef enum {
|
|
CEC_XMIT_STARTBIT,
|
|
CEC_XMIT_BIT7,
|
|
CEC_XMIT_BIT6,
|
|
CEC_XMIT_BIT5,
|
|
CEC_XMIT_BIT4,
|
|
CEC_XMIT_BIT3,
|
|
CEC_XMIT_BIT2,
|
|
CEC_XMIT_BIT1,
|
|
CEC_XMIT_BIT0,
|
|
CEC_XMIT_BIT_EOM,
|
|
CEC_XMIT_BIT_ACK,
|
|
CEC_XMIT_ACK_PU,
|
|
CEC_XMIT_CHECK_ACK,
|
|
CEC_XMIT_ACK_END,
|
|
|
|
CEC_WAIT_IDLE,
|
|
CEC_RECEIVE,
|
|
CEC_CONTINUE_BIT,
|
|
} CEC_XMIT_STATE ;
|
|
|
|
static void cec_start_bit()
|
|
{
|
|
cec_state = CEC_XMIT_STARTBIT;
|
|
gpio_direction_output(TCFG_HDMI_CEC_PORT, 0);
|
|
gpio_set_pull_down(TCFG_HDMI_CEC_PORT, 0);
|
|
|
|
const u16 low_time = 3700;
|
|
const u16 high_time = 4500 - low_time;
|
|
cec_set_wait_time(low_time);
|
|
high_period_time = high_time;
|
|
|
|
}
|
|
static void cec_logic_bit0()
|
|
{
|
|
const u16 low_time = 1500;
|
|
const u16 high_time = 2400 - low_time;
|
|
cec_set_wait_time(low_time);
|
|
cec_set_line_state(0);
|
|
high_period_time = high_time;
|
|
}
|
|
static void cec_logic_bit1()
|
|
{
|
|
const u16 low_time = 600;
|
|
const u16 high_time = 2400 - low_time;
|
|
cec_set_wait_time(low_time);
|
|
cec_set_line_state(0);
|
|
high_period_time = high_time;
|
|
}
|
|
static void cec_end_bit()
|
|
{
|
|
const u16 low_time = 600;
|
|
cec_set_line_state(0);
|
|
cec_set_wait_time(low_time);
|
|
}
|
|
static void cec_ack_bit()
|
|
{
|
|
const u16 low_time = 1500;
|
|
const u16 high_time = 1800 - low_time;
|
|
cec_set_wait_time(low_time);
|
|
cec_set_line_state(0);
|
|
high_period_time = high_time;
|
|
}
|
|
static void transmit_complete(u32 state)
|
|
{
|
|
gpio_set_direction(TCFG_HDMI_CEC_PORT, 1);
|
|
cec_work_mode = CEC_IDLE;
|
|
cec_frame.ack = state;
|
|
cec_state = CEC_RECEIVE;
|
|
}
|
|
static void tx_bit_isr()
|
|
{
|
|
if (high_period_time) {
|
|
cec_set_line_state(1);
|
|
cec_set_wait_time(high_period_time);
|
|
high_period_time = 0;
|
|
cec_state++;
|
|
return;
|
|
}
|
|
switch (cec_state) {
|
|
case CEC_WAIT_IDLE:
|
|
cec_start_bit();
|
|
break;
|
|
|
|
case CEC_XMIT_STARTBIT:
|
|
break;
|
|
|
|
case CEC_XMIT_ACK_END:
|
|
if (cec_frame.ack) {
|
|
cec_set_line_state(1);
|
|
if (cec_frame.tx_count == cec_frame.msg_len) {
|
|
transmit_complete(CEC_SUCC);
|
|
break;
|
|
} else {
|
|
cec_state = CEC_XMIT_BIT7;
|
|
}
|
|
} else {
|
|
if (cec_frame.tx_count == 1) {
|
|
transmit_complete(NAK_HEAD);
|
|
} else {
|
|
transmit_complete(NAK_DATA);
|
|
}
|
|
break;
|
|
}
|
|
case CEC_XMIT_BIT7 ... CEC_XMIT_BIT0:
|
|
if (cec_frame.msg[cec_frame.tx_count] & BIT(7 - (cec_state - CEC_XMIT_BIT7))) {
|
|
cec_logic_bit1();
|
|
} else {
|
|
cec_logic_bit0();
|
|
}
|
|
break;
|
|
|
|
case CEC_XMIT_BIT_EOM:
|
|
cec_frame.tx_count++;
|
|
if (cec_frame.tx_count == cec_frame.msg_len) {
|
|
cec_logic_bit1();
|
|
} else {
|
|
cec_logic_bit0();
|
|
}
|
|
break;
|
|
|
|
case CEC_XMIT_BIT_ACK:
|
|
cec_state++;
|
|
cec_end_bit();
|
|
break;
|
|
|
|
case CEC_XMIT_ACK_PU:
|
|
gpio_set_direction(TCFG_HDMI_CEC_PORT, 1);
|
|
cec_set_wait_time(1000 - 600);
|
|
cec_state++;
|
|
break;
|
|
|
|
case CEC_XMIT_CHECK_ACK:
|
|
cec_frame.ack = cec_frame.broadcast ? 1 : !cec_get_line_state();
|
|
cec_state++;
|
|
cec_set_wait_time(2400 - 1000);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
#define CAP_DIV 64
|
|
#define CAP_CLK 24000000
|
|
#define CEC_TMR JL_TIMER2
|
|
#define CEC_TMR_IDX IRQ_TIME2_IDX
|
|
|
|
#define CAP_RISING_EDGE 0b10
|
|
#define CAP_FALLING_EDGE 0b11
|
|
static void change_capture_mode(u32 mode)
|
|
{
|
|
CEC_TMR->PRD = 0;
|
|
CEC_TMR->CNT = 0;
|
|
CEC_TMR->CON = ((0b0011 << 4) | BIT(3));
|
|
CEC_TMR->CON |= mode;
|
|
}
|
|
static u16 get_captrue_time()
|
|
{
|
|
return CEC_TMR->PRD;
|
|
}
|
|
//New initiator wants to send a frame wait time
|
|
#define _ms *1//000
|
|
#define CEC_NEW_FRAME_WAIT_TIME (5*(2.4 _ms))//(5*(2.4 _ms))
|
|
#define CEC_RETRANSMIT_FRAME (3*(2.4 _ms))
|
|
|
|
static void cec_set_wait_time(u32 us)
|
|
{
|
|
/* us = 3700; */
|
|
CEC_TMR->CON = BIT(14);
|
|
u32 clk = clk_get("timer") / 320000;
|
|
/* printf("clk %d %d %d", clk, us, us / 100 * clk); */
|
|
CEC_TMR->CON = ((0b0110 << 4) | BIT(3));
|
|
CEC_TMR->CNT = 0;
|
|
CEC_TMR->PRD = us / 100 * clk;
|
|
CEC_TMR->CON |= BIT(0);
|
|
}
|
|
static u32 cec_bit_time_check(u16 t, u16 min, u16 max)
|
|
{
|
|
const u16 _min = min * (CAP_CLK / 1000000) / CAP_DIV;
|
|
const u16 _max = max * (CAP_CLK / 1000000) / CAP_DIV;
|
|
if ((t > _min) && (t < _max)) {
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
static s8 cec_get_bit_value(const u16 low_time, const u16 high_time)
|
|
{
|
|
if (cec_bit_time_check(low_time + high_time, 2050, 2750)) {
|
|
if (cec_bit_time_check(low_time, 400, 800)) {
|
|
return 1;
|
|
} else if (cec_bit_time_check(low_time, 1300, 1700)) {
|
|
return 0;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
static void cec_cmd_response();
|
|
static void rx_bit_isr()
|
|
{
|
|
static u16 low_time = 0;
|
|
static u16 high_time = 0;
|
|
static u16 eom = 0;
|
|
static u8 follower = 0;
|
|
u32 mode = CEC_TMR->CON & 0x3;
|
|
CEC_TMR->CON = 0;
|
|
|
|
if (high_period_time) {
|
|
cec_set_line_state(1);
|
|
cec_set_wait_time(high_period_time);
|
|
high_period_time = 0;
|
|
cec_state = CEC_XMIT_ACK_END;
|
|
return;
|
|
}
|
|
|
|
if (cec_state == CEC_XMIT_ACK_END) {
|
|
gpio_set_direction(TCFG_HDMI_CEC_PORT, 1);
|
|
__this->rx_count ++;
|
|
if (eom) {
|
|
__this->rx_msg = 1;
|
|
u16 ttmp;
|
|
ttmp = usr_timeout_add(NULL, cec_cmd_response, CEC_NEW_FRAME_WAIT_TIME, 0);
|
|
// printf("****ttmp = 0x%x\n", ttmp);
|
|
} else {
|
|
cec_state = CEC_CONTINUE_BIT;
|
|
}
|
|
|
|
change_capture_mode(CAP_FALLING_EDGE);
|
|
return;
|
|
}
|
|
|
|
u16 time = get_captrue_time();
|
|
|
|
if (mode == CAP_RISING_EDGE) {
|
|
low_time = time;
|
|
time = 0;
|
|
mode = CAP_FALLING_EDGE;
|
|
} else {
|
|
mode = CAP_RISING_EDGE;
|
|
}
|
|
|
|
change_capture_mode(mode);
|
|
|
|
if (time == 0) {
|
|
return;
|
|
}
|
|
|
|
if (cec_state == CEC_RECEIVE) {
|
|
cec_state = CEC_XMIT_STARTBIT;
|
|
low_time = 0;
|
|
high_time = 0;
|
|
return;
|
|
}
|
|
|
|
s8 bit;
|
|
|
|
high_time = time;
|
|
|
|
switch (cec_state) {
|
|
case CEC_XMIT_STARTBIT:
|
|
if (low_time && high_time) {
|
|
if (cec_bit_time_check(low_time, 3500, 3900) &&
|
|
cec_bit_time_check(low_time + high_time, 4300, 4700)) {
|
|
cec_state ++;
|
|
}
|
|
}
|
|
|
|
follower = 0;
|
|
__this->rx_count = 0;
|
|
low_time = 0;
|
|
high_time = 0;
|
|
break;
|
|
|
|
case CEC_CONTINUE_BIT:
|
|
cec_state = CEC_XMIT_BIT7;
|
|
break;
|
|
|
|
case CEC_XMIT_BIT7 ... CEC_XMIT_BIT0:
|
|
bit = cec_get_bit_value(low_time, high_time);
|
|
if (bit == 0) {
|
|
__this->msg[__this->rx_count] &= ~BIT(7 - (cec_state - CEC_XMIT_BIT7));
|
|
// cec_state++;
|
|
} else if (bit == 1) {
|
|
__this->msg[__this->rx_count] |= BIT(7 - (cec_state - CEC_XMIT_BIT7));
|
|
// cec_state++;
|
|
} else if (bit == -1) { //error bit
|
|
cec_state = CEC_XMIT_STARTBIT;
|
|
}
|
|
cec_state++;
|
|
break;
|
|
|
|
case CEC_XMIT_BIT_EOM:
|
|
cec_state++;
|
|
bit = cec_get_bit_value(low_time, high_time);
|
|
if (bit == 0) {
|
|
eom = 0;
|
|
} else if (bit == 1) {
|
|
eom = 1;
|
|
} else if (bit == -1) { //error bit
|
|
cec_state = CEC_XMIT_STARTBIT;
|
|
}
|
|
if (__this->rx_count == 0) { //head block
|
|
follower = __this->msg[0] & 0xf;
|
|
}
|
|
|
|
if (follower == __this->logic_addr) {
|
|
cec_ack_bit();//send ack
|
|
} else {
|
|
/* printf(" %d %d %d", __this->rx_count, follower, __this->logic_addr); */
|
|
__this->rx_count = 0;
|
|
}
|
|
break;
|
|
|
|
case CEC_XMIT_BIT_ACK:
|
|
cec_state = CEC_XMIT_BIT7;
|
|
break;
|
|
}
|
|
|
|
}
|
|
#define TIME_PRD 30
|
|
___interrupt
|
|
static void cec_timer_isr()
|
|
{
|
|
CEC_TMR->CON |= BIT(14);
|
|
|
|
if (cec_work_mode == CEC_TX) {
|
|
tx_bit_isr();
|
|
if (cec_work_mode == CEC_IDLE) {
|
|
change_capture_mode(CAP_FALLING_EDGE);
|
|
}
|
|
} else {
|
|
|
|
if (__this->idle_time < (150 / TIME_PRD)) {
|
|
__this->idle_time = 150 / TIME_PRD;
|
|
}
|
|
|
|
rx_bit_isr();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
u32 cec_transmit_frame(unsigned char *buffer, int count)
|
|
{
|
|
if (cec_work_mode != CEC_IDLE) {
|
|
return 1;
|
|
}
|
|
__this->idle_time = 1;
|
|
cec_work_mode = CEC_TX;
|
|
CEC_TMR->CON = BIT(14);
|
|
cec_frame.ack = -1;
|
|
cec_frame.msg = buffer;
|
|
cec_frame.msg_len = count;
|
|
cec_frame.tx_count = 0;
|
|
cec_frame.broadcast = 0;
|
|
|
|
if ((buffer[0] & 0xf) == CEC_LOGADDR_UNREGORBC) {
|
|
cec_frame.broadcast = 1;
|
|
}
|
|
|
|
if ((buffer[0] & 0xf) == __this->logic_addr) {
|
|
cec_frame.broadcast = 1;
|
|
}
|
|
|
|
gpio_set_direction(TCFG_HDMI_CEC_PORT, 1);
|
|
if (cec_get_line_state()) {
|
|
/* g_printf("start"); */
|
|
cec_start_bit();
|
|
} else {
|
|
/* g_printf("wait idle"); */
|
|
high_period_time = 0;
|
|
cec_state = CEC_WAIT_IDLE;
|
|
change_capture_mode(CAP_RISING_EDGE);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
typedef enum {
|
|
ARC_STATUS_REQ_ADD,
|
|
ARC_STATUS_WAIT_ONLINE,
|
|
ARC_STATUS_REPORT_ADD,
|
|
ARC_STATUS_STB,
|
|
ARC_STATUS_INIT,
|
|
ARC_STATUS_REQ_INIT,
|
|
ARC_STATUS_INIT_SUCCESS,
|
|
ARC_STATUS_TERMINATE,
|
|
ARC_STATUS_REQ_TERMINATE,
|
|
ARC_STATUS_REPORT_TERMINATE,
|
|
} ARC_STATUS;
|
|
|
|
static void decode_cec_command()
|
|
{
|
|
printf("CEC command ");
|
|
put_buf(__this->msg, __this->rx_count);
|
|
u8 intiator = __this->msg[0] >> 4;
|
|
switch (__this->msg[1]) {
|
|
case CECOP_FEATURE_ABORT:
|
|
printf("__this->state < ARC_STATUS_INIT=0x%x\n", __this->state);
|
|
if (__this->state <= ARC_STATUS_INIT) {
|
|
// putchar('2');
|
|
__this->cec_ok = 0;
|
|
__this->state = ARC_STATUS_REQ_ADD;
|
|
}
|
|
break;
|
|
case CECOP_GIVE_PHYSICAL_ADDRESS:
|
|
cec_transmit_frame(Report_Physical_Add_Cmd, 5);
|
|
break;
|
|
case CECOP_GIVE_DEVICE_VENDOR_ID:
|
|
cec_transmit_frame(Device_Vendor_Id_Cmd, 5);
|
|
break;
|
|
case GET_CEC_VERSION:
|
|
CEC_Version_cmd[0] = intiator;
|
|
cec_transmit_frame(CEC_Version_cmd, 3);
|
|
break;
|
|
case CECOP_ARC_REPORT_INITIATED:
|
|
__this->idle_time = 500 / TIME_PRD;
|
|
break;
|
|
|
|
case CECOP_SET_STREAM_PATH:
|
|
break;
|
|
case CECOP_GIVE_OSD_NAME:
|
|
cec_transmit_frame(Set_Osd_Name_cmd, 14);
|
|
break;
|
|
|
|
case CECOP_REQUEST_SHORT_AUDIO:
|
|
__this->cec_ok = 1;
|
|
cec_transmit_frame(Report_Short_Audio_Desc_cmd, sizeof(Report_Short_Audio_Desc_cmd));
|
|
__this->idle_time = 3500 / TIME_PRD;
|
|
break;
|
|
|
|
case CECOP_SYSTEM_AUDIO_MODE_REQUEST:
|
|
// cec_transmit_frame(Set_System_Audio_Mode_cmd, sizeof(Set_System_Audio_Mode_cmd));
|
|
cec_transmit_frame(Broadcast_System_Audio_Mode_cmd, sizeof(Set_System_Audio_Mode_cmd));
|
|
break;
|
|
case CECOP_GIVE_AUDIO_STATUS:
|
|
cec_transmit_frame(Report_Audio_Status_cmd, sizeof(Report_Audio_Status_cmd));
|
|
break;
|
|
|
|
case CECOP_GIVE_SYSTEM_AUDIO_MODE_STATUS:
|
|
cec_transmit_frame(System_Audio_Mode_Status_cmd, sizeof(System_Audio_Mode_Status_cmd));
|
|
break;
|
|
case CECOP_TUNER_DEVICE_STATUS:
|
|
cec_transmit_frame(Give_Tuner_Device_Status_cmd, sizeof(Give_Tuner_Device_Status_cmd) / sizeof(Give_Tuner_Device_Status_cmd[0]));
|
|
break;
|
|
case CECOP_GIVE_DEVICE_POWER_STATUS:
|
|
cec_transmit_frame(Report_Power_Status_cmd, sizeof(Report_Power_Status_cmd));
|
|
break;
|
|
case CECOP_ARC_REQUEST_INITIATION:
|
|
cec_transmit_frame(Initiate_Arc_cmd, 2);
|
|
__this->state = ARC_STATUS_INIT;
|
|
__this->idle_time = 3500 / TIME_PRD;
|
|
break;
|
|
|
|
default:
|
|
printf("CEC command ");
|
|
put_buf(__this->msg, __this->rx_count);
|
|
break;
|
|
}
|
|
}
|
|
static void cec_cmd_response()
|
|
{
|
|
if (__this->rx_count > 1) {
|
|
decode_cec_command();
|
|
}
|
|
|
|
// putchar('1');
|
|
if (__this->idle_time < (150 / TIME_PRD)) {
|
|
__this->idle_time = 150 / TIME_PRD;
|
|
}
|
|
|
|
if (cec_work_mode == CEC_IDLE) {
|
|
cec_state = CEC_RECEIVE;
|
|
}
|
|
if (__this->msg_count != 0) {
|
|
__this->msg_count = 0xff;
|
|
}
|
|
__this->rx_msg = 0;
|
|
}
|
|
static void cec_timer_loop()
|
|
{
|
|
if (__this->rx_msg) {
|
|
return;
|
|
}
|
|
|
|
if (cec_work_mode) {
|
|
return;
|
|
}
|
|
|
|
if (__this->idle_time) {
|
|
__this->idle_time--;
|
|
return;
|
|
}
|
|
|
|
if (__this->msg_count && cec_frame.ack != CEC_SUCC) {
|
|
__this->msg_count = 0;
|
|
r_printf("send cec msg nak %d", cec_frame.ack);
|
|
} else {
|
|
}
|
|
|
|
printf("[%d]", __this->state);
|
|
switch (__this->state) {
|
|
|
|
case ARC_STATUS_REQ_ADD:
|
|
if (__this->msg_count == 0xff) {
|
|
__this->state = ARC_STATUS_REPORT_ADD;
|
|
__this->msg_count = 0;
|
|
break;
|
|
}
|
|
__this->cec_ok = 0;
|
|
cec_transmit_frame(PollingMessage_cmd, 1);
|
|
__this->msg_count ++;
|
|
|
|
if (__this->msg_count == 2) {
|
|
__this->idle_time = 50 / TIME_PRD;
|
|
}
|
|
if (__this->msg_count > 3) {
|
|
__this->state = ARC_STATUS_REPORT_ADD;
|
|
__this->idle_time = 50 / TIME_PRD;
|
|
__this->msg_count = 0;
|
|
}
|
|
break;
|
|
|
|
case ARC_STATUS_REPORT_ADD:
|
|
__this->logic_addr = 5;
|
|
if (__this->msg_count == 0xff) {
|
|
__this->state = ARC_STATUS_WAIT_ONLINE;
|
|
__this->msg_count = 0;
|
|
break;
|
|
}
|
|
// __this->cec_ok=1;
|
|
cec_transmit_frame(Report_Physical_Add_Cmd1, 5);
|
|
__this->msg_count ++;
|
|
if (__this->msg_count > 1) {
|
|
__this->state = ARC_STATUS_WAIT_ONLINE;
|
|
__this->msg_count = 0;
|
|
}
|
|
break;
|
|
|
|
case ARC_STATUS_WAIT_ONLINE:
|
|
if (__this->msg_count == 0xff) {
|
|
__this->state = ARC_STATUS_STB;
|
|
__this->msg_count = 0;
|
|
break;
|
|
}
|
|
cec_transmit_frame(Device_Vendor_Id_Cmd, 5);
|
|
__this->msg_count ++;
|
|
if (__this->msg_count > 1) {
|
|
__this->state = ARC_STATUS_STB;
|
|
__this->msg_count = 0;
|
|
}
|
|
break;
|
|
|
|
case ARC_STATUS_STB:
|
|
if (__this->msg_count == 0xff) {
|
|
__this->state = ARC_STATUS_INIT;
|
|
__this->msg_count = 0;
|
|
break;
|
|
}
|
|
__this->cec_ok = 1;
|
|
// cec_transmit_frame(Set_System_Audio_Mode_cmd, 3);
|
|
cec_transmit_frame(Broadcast_System_Audio_Mode_cmd, 3);
|
|
__this->msg_count ++;
|
|
__this->idle_time = 300 / TIME_PRD;
|
|
if (__this->msg_count > 1) {
|
|
__this->state = ARC_STATUS_INIT;
|
|
}
|
|
break;
|
|
|
|
case ARC_STATUS_INIT:
|
|
if (__this->cec_ok) {
|
|
break;
|
|
}
|
|
cec_transmit_frame(Initiate_Arc_cmd, 2);
|
|
__this->idle_time = 3500 / TIME_PRD;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void hdmi_cec_init(void)
|
|
{
|
|
memset(__this, 0, sizeof(*__this));
|
|
|
|
__this->logic_addr = 5;
|
|
cec_state = CEC_RECEIVE;
|
|
cec_work_mode = CEC_IDLE;
|
|
__this->cec_ok = 0;
|
|
|
|
//port
|
|
gpio_set_die(TCFG_HDMI_CEC_PORT, 1);
|
|
gpio_set_direction(TCFG_HDMI_CEC_PORT, 1);
|
|
gpio_set_pull_up(TCFG_HDMI_CEC_PORT, 1);
|
|
gpio_set_pull_down(TCFG_HDMI_CEC_PORT, 0);
|
|
|
|
u32 clk = clk_get("timer");
|
|
printf("clk %d %d", clk, CAP_CLK);
|
|
|
|
#if CEC_TMR_IDX == IRQ_TIME2_IDX
|
|
//capture input channel
|
|
printf("TCFG_HDMI_CEC_PORT:[%d]", TCFG_HDMI_CEC_PORT);
|
|
JL_IOMAP->CON1 |= BIT(30);
|
|
JL_IOMAP->CON2 &= ~(0x7F << 16);
|
|
JL_IOMAP->CON2 |= (TCFG_HDMI_CEC_PORT << 16);
|
|
|
|
CEC_TMR->CON = BIT(14);
|
|
#else
|
|
#error "please config time input channle"
|
|
#endif
|
|
change_capture_mode(CAP_FALLING_EDGE);
|
|
request_irq(CEC_TMR_IDX, 2, cec_timer_isr, 0);
|
|
__this->time_id = sys_timer_add(NULL, cec_timer_loop, TIME_PRD);
|
|
g_printf("add timer %x", __this->time_id);
|
|
}
|
|
|
|
void hdmi_cec_close(void)
|
|
{
|
|
CEC_TMR->CON = BIT(14);
|
|
__this->cec_ok = 0;
|
|
|
|
gpio_set_direction(TCFG_HDMI_CEC_PORT, 1);
|
|
gpio_set_pull_up(TCFG_HDMI_CEC_PORT, 0);
|
|
gpio_set_die(TCFG_HDMI_CEC_PORT, 0);
|
|
|
|
g_printf("del timer %x", __this->time_id);
|
|
if (__this->time_id) {
|
|
sys_timer_del(__this->time_id);
|
|
__this->time_id = 0;
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|