void tx_irq_handle(void) { unsigned tx_status = aocec_rd_reg(CEC_TX_MSG_STATUS); switch (tx_status) { case TX_DONE: aocec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP); break; case TX_BUSY: aocec_wr_reg(CEC_TX_MSG_CMD, TX_ABORT); aocec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP); break; case TX_ERROR: if (cec_msg_dbg_en == 1) hdmi_print(INF, CEC "TX ERROR!!!\n"); if (RX_ERROR == aocec_rd_reg(CEC_RX_MSG_STATUS)) { cec_hw_reset(); } else { aocec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP); } //aocec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP); break; default: break; } aml_write_reg32(P_AO_CEC_INTR_CLR, aml_read_reg32(P_AO_CEC_INTR_CLR) | (1 << 1)); //aml_write_reg32(P_AO_CEC_INTR_MASKN, aml_read_reg32(P_AO_CEC_INTR_MASKN) | (1 << 2)); }
static int ao_cec_ll_tx_polling(const unsigned char *msg, unsigned char len) { int i; unsigned int ret = 0xf; unsigned int n; unsigned int j = 30; while( aocec_rd_reg(CEC_TX_MSG_STATUS)){ if(TX_ERROR == aocec_rd_reg(CEC_TX_MSG_STATUS)){ //aocec_wr_reg(CEC_TX_MSG_CMD, TX_ABORT); aocec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP); //cec_hw_reset(); break; } if(!(j--)){ hdmi_print(INF, CEC "tx busy time out.\n"); aocec_wr_reg(CEC_TX_MSG_CMD, TX_ABORT); aocec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP); break; } msleep(5); } aml_set_reg32_bits(P_AO_CEC_INTR_MASKN, 0x0, 1, 1); for (i = 0; i < len; i++) { aocec_wr_reg(CEC_TX_MSG_0_HEADER + i, msg[i]); } aocec_wr_reg(CEC_TX_MSG_LENGTH, len-1); aocec_wr_reg(CEC_TX_MSG_CMD, RX_ACK_CURRENT); j = 30; while((TX_DONE != aocec_rd_reg(CEC_TX_MSG_STATUS)) && (j--)){ if(TX_ERROR == aocec_rd_reg(CEC_TX_MSG_STATUS)) break; msleep(5); } ret = aocec_rd_reg(CEC_TX_MSG_STATUS); if(ret == TX_DONE) ret = 1; else ret = 0; aocec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP); aml_set_reg32_bits(P_AO_CEC_INTR_MASKN, 1, 1, 1); msleep(100); if(cec_msg_dbg_en == 1) { pos = 0; pos += sprintf(msg_log_buf + pos, "CEC: tx msg len: %d dat: ", len); for(n = 0; n < len; n++) { pos += sprintf(msg_log_buf + pos, "%02x ", msg[n]); } pos += sprintf(msg_log_buf + pos, "\nCEC: tx state: %d\n", ret); msg_log_buf[pos] = '\0'; printk("%s", msg_log_buf); } return ret; }
static int ao_cec_ll_rx( unsigned char *msg, unsigned char *len) { unsigned char i; unsigned char data; unsigned char n; unsigned char *msg_start = msg; unsigned int num; int rx_msg_length; int rx_status; rx_status = aocec_rd_reg(CEC_RX_MSG_STATUS); num = aocec_rd_reg(CEC_RX_NUM_MSG); printk("rx irq:rx_status:0x%x:: num :0x%x\n", rx_status, num); //aml_set_reg32_bits(P_AO_CEC_INTR_CLR, 1, 2, 1); if(RX_DONE != rx_status){ printk("rx irq:!!!RX_DONE\n"); aocec_wr_reg(CEC_RX_MSG_CMD, RX_ACK_CURRENT); aocec_wr_reg(CEC_RX_MSG_CMD, RX_NO_OP); return -1; } if(1 != num){ printk("rx irq:!!!num\n"); //aocec_wr_reg(CEC_RX_MSG_CMD, RX_ACK_CURRENT); //aocec_wr_reg(CEC_RX_MSG_CMD, RX_NO_OP); aocec_wr_reg(CEC_RX_CLEAR_BUF, 1); aml_set_reg32_bits(P_AO_CEC_INTR_CLR, 1, 2, 1); return -1; } rx_msg_length = aocec_rd_reg(CEC_RX_MSG_LENGTH) + 1; aocec_wr_reg(CEC_RX_MSG_CMD, RX_ACK_CURRENT); for (i = 0; i < rx_msg_length && i < MAX_MSG; i++) { data = aocec_rd_reg(CEC_RX_MSG_0_HEADER +i); *msg = data; msg++; } *len = rx_msg_length; rx_status = aocec_rd_reg(CEC_RX_MSG_STATUS); aocec_wr_reg(CEC_RX_MSG_CMD, RX_NO_OP); //aocec_wr_reg(CEC_RX_CLEAR_BUF, 1); aml_set_reg32_bits(P_AO_CEC_INTR_CLR, 1, 2, 1); cec_hw_reset(); if(cec_msg_dbg_en == 1){ pos = 0; pos += sprintf(msg_log_buf + pos, "CEC: rx msg len: %d dat: ", rx_msg_length); for(n = 0; n < rx_msg_length; n++) { pos += sprintf(msg_log_buf + pos, "%02x ", msg_start[n]); } pos += sprintf(msg_log_buf + pos, "\n"); msg_log_buf[pos] = '\0'; hdmi_print(INF, CEC "%s", msg_log_buf); } return rx_status; }
// return value: 1: successful 0: error static int cec_ll_tx_once(const unsigned char *msg, unsigned char len) { int i; unsigned int ret = 0xf; unsigned int n; unsigned int cnt = 30; int pos; while (aocec_rd_reg(CEC_TX_MSG_STATUS) || aocec_rd_reg(CEC_RX_MSG_STATUS)) { msleep(5); if (TX_ERROR == aocec_rd_reg(CEC_TX_MSG_STATUS)) { if (cec_msg_dbg_en == 1) hdmi_print(INF, CEC "tx once:tx error!\n"); //aocec_wr_reg(CEC_TX_MSG_CMD, TX_ABORT); aocec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP); //cec_hw_reset(); break; } if (!(cnt--)) { if (cec_msg_dbg_en == 1) hdmi_print(INF, CEC "tx busy time out.\n"); aocec_wr_reg(CEC_TX_MSG_CMD, TX_ABORT); aocec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP); break; } } for (i = 0; i < len; i++) { aocec_wr_reg(CEC_TX_MSG_0_HEADER + i, msg[i]); } aocec_wr_reg(CEC_TX_MSG_LENGTH, len-1); aocec_wr_reg(CEC_TX_MSG_CMD, TX_REQ_CURRENT); if (cec_msg_dbg_en == 1) { pos = 0; pos += sprintf(msg_log_buf + pos, "CEC: tx msg len: %d dat: ", len); for (n = 0; n < len; n++) { pos += sprintf(msg_log_buf + pos, "%02x ", msg[n]); } pos += sprintf(msg_log_buf + pos, "\n"); msg_log_buf[pos] = '\0'; printk("%s", msg_log_buf); } return ret; }
int cec_ll_rx( unsigned char *msg, unsigned char *len) { unsigned char i; unsigned char rx_status; unsigned char data; unsigned char msg_log_buf[128]; int pos; unsigned char n; unsigned char *msg_start = msg; int rx_msg_length; if(RX_DONE != aocec_rd_reg(CEC_RX_MSG_STATUS)){ aocec_wr_reg(CEC_RX_MSG_CMD, RX_ACK_CURRENT); aocec_wr_reg(CEC_RX_MSG_CMD, RX_NO_OP); return -1; } if(1 != aocec_rd_reg(CEC_RX_NUM_MSG)){ aocec_wr_reg(CEC_RX_MSG_CMD, RX_ACK_CURRENT); aocec_wr_reg(CEC_RX_MSG_CMD, RX_NO_OP); return -1; } rx_msg_length = aocec_rd_reg(CEC_RX_MSG_LENGTH) + 1; aocec_wr_reg(CEC_RX_MSG_CMD, RX_ACK_CURRENT); for (i = 0; i < rx_msg_length && i < MAX_MSG; i++) { data = aocec_rd_reg(CEC_RX_MSG_0_HEADER +i); *msg = data; msg++; } *len = rx_msg_length; rx_status = aocec_rd_reg(CEC_RX_MSG_STATUS); aocec_wr_reg(CEC_RX_MSG_CMD, RX_NO_OP); aml_write_reg32(P_AO_CEC_INTR_CLR, aml_read_reg32(P_AO_CEC_INTR_CLR) | (1 << 2)); if(cec_msg_dbg_en == 1){ pos = 0; pos += sprintf(msg_log_buf + pos, "CEC: rx msg len: %d dat: ", rx_msg_length); for(n = 0; n < rx_msg_length; n++) { pos += sprintf(msg_log_buf + pos, "%02x ", msg_start[n]); } pos += sprintf(msg_log_buf + pos, "\n"); msg_log_buf[pos] = '\0'; hdmi_print(INF, CEC "%s", msg_log_buf); } return rx_status; }
void cec_hw_reset(void) { //unsigned long data32; // Assert SW reset AO_CEC //data32 = 0; //data32 |= 0 << 1; // [2:1] cntl_clk: 0=Disable clk (Power-off mode); 1=Enable gated clock (Normal mode); 2=Enable free-run clk (Debug mode). //data32 |= 1 << 0; // [0] sw_reset: 1=Reset aml_write_reg32(P_AO_CEC_GEN_CNTL, 0x1); // Enable gated clock (Normal mode). aml_set_reg32_bits(P_AO_CEC_GEN_CNTL, 1, 1, 1); // Release SW reset aml_set_reg32_bits(P_AO_CEC_GEN_CNTL, 0, 0, 1); // Enable all AO_CEC interrupt sources if (!cec_int_disable_flag) aml_set_reg32_bits(P_AO_CEC_INTR_MASKN, 0x6, 0, 3); aocec_wr_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | cec_global_info.my_node_index); //Cec arbitration 3/5/7 bit time set. cec_arbit_bit_time_set(3, 0x118, 0); cec_arbit_bit_time_set(5, 0x000, 0); cec_arbit_bit_time_set(7, 0x2aa, 0); hdmi_print(INF, CEC "hw reset :logical addr:0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR0)); }
int cec_ll_rx( unsigned char *msg, unsigned char *len) { int i; int ret = -1; int pos; if ((RX_DONE != aocec_rd_reg(CEC_RX_MSG_STATUS)) || (1 != aocec_rd_reg(CEC_RX_NUM_MSG))) { //cec_rx_buf_check(); aml_write_reg32(P_AO_CEC_INTR_CLR, aml_read_reg32(P_AO_CEC_INTR_CLR) | (1 << 2)); aocec_wr_reg(CEC_RX_MSG_CMD, RX_ACK_CURRENT); aocec_wr_reg(CEC_RX_MSG_CMD, RX_NO_OP); return ret; } *len = aocec_rd_reg(CEC_RX_MSG_LENGTH) + 1; for (i = 0; i < (*len) && i < MAX_MSG; i++) { msg[i]= aocec_rd_reg(CEC_RX_MSG_0_HEADER +i); } ret = aocec_rd_reg(CEC_RX_MSG_STATUS); if (cec_msg_dbg_en == 1) { pos = 0; pos += sprintf(msg_log_buf + pos, "CEC: rx msg len: %d dat: ", *len); for (i = 0; i < (*len); i++) { pos += sprintf(msg_log_buf + pos, "%02x ", msg[i]); } pos += sprintf(msg_log_buf + pos, "\n"); msg_log_buf[pos] = '\0'; hdmi_print(INF, CEC "%s", msg_log_buf); } //cec_rx_buf_check(); aml_write_reg32(P_AO_CEC_INTR_CLR, aml_read_reg32(P_AO_CEC_INTR_CLR) | (1 << 2)); aocec_wr_reg(CEC_RX_MSG_CMD, RX_ACK_CURRENT); aocec_wr_reg(CEC_RX_MSG_CMD, RX_NO_OP); //aml_write_reg32(P_AO_CEC_INTR_CLR, aml_read_reg32(P_AO_CEC_INTR_CLR) | (1 << 2)); return ret; }
int cec_rx_buf_check(void) { if (0xf == aocec_rd_reg(CEC_RX_NUM_MSG)) { aocec_wr_reg(CEC_RX_CLEAR_BUF, 0x1); aocec_wr_reg(CEC_RX_CLEAR_BUF, 0x0); hdmi_print(INF, CEC "rx buf clean\n"); return 1; } return 0; }
int cec_ll_tx_polling(const unsigned char *msg, unsigned char len) { int i; unsigned int ret = 0xf; unsigned int n; unsigned int j = 30; int pos; aml_set_reg32_bits(P_AO_CEC_INTR_MASKN, 0x0, 1, 1); for (i = 0; i < len; i++) { aocec_wr_reg(CEC_TX_MSG_0_HEADER + i, msg[i]); } aocec_wr_reg(CEC_TX_MSG_LENGTH, len-1); aocec_wr_reg(CEC_TX_MSG_CMD, RX_ACK_CURRENT); while((TX_DONE != aocec_rd_reg(CEC_TX_MSG_STATUS)) && (j--)){ msleep(5); } ret = aocec_rd_reg(CEC_TX_MSG_STATUS); if(ret == TX_DONE) ret = 1; else ret = 0; aocec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP); aml_set_reg32_bits(P_AO_CEC_INTR_MASKN, 1, 1, 1); if(cec_msg_dbg_en == 1) { pos = 0; pos += sprintf(msg_log_buf + pos, "CEC: tx msg len: %d dat: ", len); for(n = 0; n < len; n++) { pos += sprintf(msg_log_buf + pos, "%02x ", msg[n]); } pos += sprintf(msg_log_buf + pos, "\nCEC: tx state: %d\n", ret); msg_log_buf[pos] = '\0'; printk("%s", msg_log_buf); } return ret; }
void tx_irq_handle(void){ unsigned tx_status = aocec_rd_reg(CEC_TX_MSG_STATUS); switch(tx_status){ case TX_DONE: aocec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP); break; case TX_BUSY: aocec_wr_reg(CEC_TX_MSG_CMD, TX_ABORT); aocec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP); break; case TX_ERROR: cec_hw_reset(); //aocec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP); break; default: break; } aml_write_reg32(P_AO_CEC_INTR_CLR, aml_read_reg32(P_AO_CEC_INTR_CLR) | (1 << 1)); //aml_write_reg32(P_AO_CEC_INTR_MASKN, aml_read_reg32(P_AO_CEC_INTR_MASKN) | (1 << 2)); }
static void ao_cec_tx_irq_handle(void) { unsigned tx_status = aocec_rd_reg(CEC_TX_MSG_STATUS); printk("tx_status:0x%x\n", tx_status); switch(tx_status){ case TX_DONE: aocec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP); break; case TX_BUSY: aocec_wr_reg(CEC_TX_MSG_CMD, TX_ABORT); aocec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP); break; case TX_ERROR: cec_hw_reset(); //aocec_wr_reg(CEC_TX_MSG_CMD, TX_ABORT); //aocec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP); break; default: break; } aml_set_reg32_bits(P_AO_CEC_INTR_CLR, 1, 1, 1); }
void cec_hw_reset(void) { hd_write_reg(P_AO_CEC_GEN_CNTL, 0x1); /* Enable gated clock (Normal mode). */ hd_set_reg_bits(P_AO_CEC_GEN_CNTL, 1, 1, 1); /* Release SW reset */ hd_set_reg_bits(P_AO_CEC_GEN_CNTL, 0, 0, 1); /* Enable all AO_CEC interrupt sources */ if (!cec_int_disable_flag) hd_set_reg_bits(P_AO_CEC_INTR_MASKN, 0x6, 0, 3); aocec_wr_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | cec_global_info.my_node_index); /* Cec arbitration 3/5/7 bit time set. */ cec_arbit_bit_time_set(3, 0x118, 0); cec_arbit_bit_time_set(5, 0x000, 0); cec_arbit_bit_time_set(7, 0x2aa, 0); hdmi_print(INF, CEC "hw reset :logical addr:0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR0)); }
mutex_unlock(&cec_mutex); return ret; } void cec_polling_online_dev(int log_addr, int *bool) { unsigned long r; unsigned char msg[1]; cec_global_info.my_node_index = log_addr; msg[0] = (log_addr<<4) | log_addr; aocec_wr_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | 0xf); hdmi_print(INF, CEC "CEC_LOGICAL_ADDR0:0x%lx\n",aocec_rd_reg(CEC_LOGICAL_ADDR0)); r = cec_ll_tx_polling(msg, 1); cec_hw_reset(); if (r == 0) { *bool = 0; }else{ memset(&(cec_global_info.cec_node_info[log_addr]), 0, sizeof(cec_node_info_t)); cec_global_info.cec_node_info[log_addr].dev_type = cec_log_addr_to_dev_type(log_addr); *bool = 1; } if(*bool == 0) { aocec_wr_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | log_addr); } hdmi_print(INF, CEC "CEC: poll online logic device: 0x%x BOOL: %d\n", log_addr, *bool);
int cec_ll_tx_polling(const unsigned char *msg, unsigned char len) { int i; unsigned int ret = 0xf; unsigned int n; unsigned int j = 30; int pos; while ((TX_BUSY == aocec_rd_reg(CEC_TX_MSG_STATUS)) || (RX_BUSY == aocec_rd_reg(CEC_RX_MSG_STATUS))) { if (TX_ERROR == aocec_rd_reg(CEC_TX_MSG_STATUS)) { if (cec_msg_dbg_en == 1) hdmi_print(INF, CEC "tx polling:tx error!.\n"); /* aocec_wr_reg(CEC_TX_MSG_CMD, TX_ABORT); */ aocec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP); /* cec_hw_reset(); */ break; } if (!(j--)) { if (cec_msg_dbg_en == 1) hdmi_print(INF, CEC "tx busy time out.\n"); aocec_wr_reg(CEC_TX_MSG_CMD, TX_ABORT); aocec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP); break; } mdelay(5); } hd_set_reg_bits(P_AO_CEC_INTR_MASKN, 0x0, 1, 1); for (i = 0; i < len; i++) aocec_wr_reg(CEC_TX_MSG_0_HEADER + i, msg[i]); aocec_wr_reg(CEC_TX_MSG_LENGTH, len-1); aocec_wr_reg(CEC_TX_MSG_CMD, RX_ACK_CURRENT); j = 30; while ((TX_DONE != aocec_rd_reg(CEC_TX_MSG_STATUS)) && (j--)) { if (TX_ERROR == aocec_rd_reg(CEC_TX_MSG_STATUS)) break; mdelay(5); } ret = aocec_rd_reg(CEC_TX_MSG_STATUS); if (ret == TX_DONE) ret = 1; else ret = 0; aocec_wr_reg(CEC_TX_MSG_CMD, TX_NO_OP); hd_set_reg_bits(P_AO_CEC_INTR_MASKN, 1, 1, 1); if (cec_msg_dbg_en == 1) { pos = 0; pos += sprintf(msg_log_buf + pos, "CEC: tx msg len: %d dat: ", len); for (n = 0; n < len; n++) pos += sprintf(msg_log_buf + pos, "%02x ", msg[n]); pos += sprintf(msg_log_buf + pos, "\nCEC: tx state: %d\n", ret); msg_log_buf[pos] = '\0'; pr_info("%s", msg_log_buf); } return ret; }