/* * Read a value from a register on ADV7525 device * If sucessfull returns value read , otherwise error. */ static u8 adv7525_read_reg(struct i2c_client *client, u8 reg) { int err; struct i2c_msg msg[2]; u8 reg_buf[] = { reg }; u8 data_buf[] = { 0 }; if (!client->adapter) return -ENODEV; if (!gpio_power_on) { DEV_WARN("%s: WARN: missing GPIO power\n", __func__); return -ENODEV; } msg[0].addr = client->addr; msg[0].flags = 0; msg[0].len = 1; msg[0].buf = reg_buf; msg[1].addr = client->addr; msg[1].flags = I2C_M_RD; msg[1].len = 1; msg[1].buf = data_buf; err = i2c_transfer(client->adapter, msg, 2); if (err < 0) { DEV_INFO("%s: I2C err: %d\n", __func__, err); return err; } #ifdef PORT_DEBUG DEV_INFO("HDMI[%02x] [R] %02x\n", reg, data); #endif return *data_buf; }
static ssize_t hdmi_common_wta_video_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { ssize_t ret = strnlen(buf, PAGE_SIZE); uint32 video_mode; const struct hdmi_disp_mode_timing_type *disp_mode; mutex_lock(&hdmi_common_state_hpd_mutex); if (!hdmi_common_state->hpd_state) { mutex_unlock(&hdmi_common_state_hpd_mutex); DEV_INFO("%s: FAILED: display off or cable disconnected\n", __func__); return ret; } mutex_unlock(&hdmi_common_state_hpd_mutex); video_mode = atoi(buf)-1; disp_mode = hdmi_common_get_supported_mode(video_mode); if (!disp_mode) { DEV_INFO("%s: FAILED: mode not supported (%d)\n", __func__, video_mode); return ret; } kobject_uevent(hdmi_common_state->uevent_kobj, KOBJ_OFFLINE); hdmi_common_state->disp_mode_list.num_of_elements = 1; hdmi_common_state->disp_mode_list.disp_mode_list[0] = video_mode; DEV_DBG("%s: 'mode=%d %s' successful (sending OFF/ONLINE)\n", __func__, video_mode, video_format_2string(video_mode)); kobject_uevent(hdmi_common_state->uevent_kobj, KOBJ_ONLINE); return ret; }
bool CGameServer::OnServerUpdate(CPAKUpdate* pUpdate, KeyRef krSocket) { bool bRet = false; switch (pUpdate->GetType()) { case PAK_TYPE_ZONE: { DEV_INFO(TF("[游戏服务器]地图服务器[%p]更新"), krSocket); bRet = ServerUpdate<SVR_ZONE_INDEX_MAP, DATA_INDEX_ZONE, INFOI_ZONE>(pUpdate, (DataRef)krSocket, m_ZoneSvrMap); } break; case PAK_TYPE_GATE: { DEV_INFO(TF("[游戏服务器]网关服务器[%p]更新"), krSocket); bRet = ServerUpdate<SVR_GATE_MAP, DATA_INDEX_GATE, INFOI_GATE>(pUpdate, (DataRef)krSocket, m_GateSvrMap); } break; default: { LOGV_WARN(m_FileLog, TF("[游戏服务器]%p无法识别的%X服务器信令包数据"), krSocket, pUpdate->GetType()); } } if (bRet) { // 发送更新回执包 CPAKSimple<PAK_EVENT_UPDATEACK, PAK_TYPE_GAME> UpdateAck; UpdateAck.AdjustSize(); m_NetworkPtr->Send(krSocket, UpdateAck); } return bRet; }
bool CGameServer::OnShareUpdate(CEventBase& EventRef, LLong llParam) { CPAKUpdate* pUpdate = static_cast<CPAKUpdate*>(&EventRef); if (pUpdate->GetType() == PAK_TYPE_ZONE) { if (m_pShareZoneSvr != nullptr) { DEV_INFO(TF("[游戏服务器]同进程地图服务器[%p]更新"), m_pShareZoneSvr); assert(m_pShareZoneSvr == reinterpret_cast<ICommonServer*>(llParam)); return ServerUpdate<SVR_ZONE_INDEX_MAP, DATA_INDEX_ZONE, INFOI_ZONE>(pUpdate, (DataRef)llParam, m_ZoneSvrMap); } else { LOGV_WARN(m_FileLog, TF("[游戏服务器]同进程地图服务器对象未注册")); } } else if (pUpdate->GetType() == PAK_TYPE_GATE) { if (m_pShareGateSvr != nullptr) { DEV_INFO(TF("[游戏服务器]同进程网关服务器[%p]更新"), m_pShareGateSvr); assert(m_pShareGateSvr == reinterpret_cast<ICommonServer*>(llParam)); return ServerUpdate<SVR_GATE_MAP, DATA_INDEX_GATE, INFOI_GATE>(pUpdate, (DataRef)llParam, m_GateSvrMap); } else { LOGV_WARN(m_FileLog, TF("[游戏服务器]同进程网关服务器对象未注册")); } } return false; }
static void adv7520_hdcp_enable(struct work_struct *work) { DEV_INFO("HDCP: Start reg[0xaf]=%02x (mute audio)\n", reg[0xaf]); adv7520_comm_power(1, 1); /* Mute Audio */ adv7520_write_reg(hclient, 0x0C, (u8)0xC3); msleep(200); /* Wait for BKSV ready interrupt */ /* Read BKSV's keys from HDTV */ reg[0xBF] = adv7520_read_reg(hclient, 0xBF); reg[0xC0] = adv7520_read_reg(hclient, 0xC0); reg[0xC1] = adv7520_read_reg(hclient, 0xC1); reg[0xC2] = adv7520_read_reg(hclient, 0xC2); reg[0xc3] = adv7520_read_reg(hclient, 0xC3); DEV_DBG("HDCP: BKSV={%02x,%02x,%02x,%02x,%02x}\n", reg[0xbf], reg[0xc0], reg[0xc1], reg[0xc2], reg[0xc3]); /* Is SINK repeater */ reg[0xBE] = adv7520_read_reg(hclient, 0xBE); if (~(reg[0xBE] & 0x40)) { ; /* compare with revocation list */ /* Check 20 1's and 20 zero's */ } else { /* Don't implement HDCP if sink as a repeater */ adv7520_write_reg(hclient, 0x0C, (u8)0x84); mutex_lock(&hdcp_state_mutex); hdcp_activating = FALSE; mutex_unlock(&hdcp_state_mutex); DEV_WARN("HDCP: Sink Repeater (%02x), (unmute audio)\n", reg[0xbe]); adv7520_comm_power(0, 1); return; } msleep(200); reg[0xB8] = adv7520_read_reg(hclient, 0xB8); DEV_INFO("HDCP: Status reg[0xB8] is %02x\n", reg[0xb8]); if (reg[0xb8] & 0x40) { /* UnMute Audio */ adv7520_write_reg(hclient, 0x0C, (u8)0x84); DEV_INFO("HDCP: A/V content Encrypted (unmute audio)\n"); external_common_state->hdcp_active = TRUE; } adv7520_comm_power(0, 1); mutex_lock(&hdcp_state_mutex); hdcp_activating = FALSE; mutex_unlock(&hdcp_state_mutex); }
static void adv7520_hdcp_enable(struct work_struct *work) { DEV_INFO("HDCP: Start reg[0xaf]=%02x (mute audio)\n", reg[0xaf]); adv7520_comm_power(1, 1); adv7520_write_reg(hclient, 0x0C, (u8)0xC3); msleep(200); reg[0xBF] = adv7520_read_reg(hclient, 0xBF); reg[0xC0] = adv7520_read_reg(hclient, 0xC0); reg[0xC1] = adv7520_read_reg(hclient, 0xC1); reg[0xC2] = adv7520_read_reg(hclient, 0xC2); reg[0xc3] = adv7520_read_reg(hclient, 0xC3); DEV_DBG("HDCP: BKSV={%02x,%02x,%02x,%02x,%02x}\n", reg[0xbf], reg[0xc0], reg[0xc1], reg[0xc2], reg[0xc3]); reg[0xBE] = adv7520_read_reg(hclient, 0xBE); if (~(reg[0xBE] & 0x40)) { ; } else { adv7520_write_reg(hclient, 0x0C, (u8)0x84); mutex_lock(&hdcp_state_mutex); hdcp_activating = FALSE; mutex_unlock(&hdcp_state_mutex); DEV_WARN("HDCP: Sink Repeater (%02x), (unmute audio)\n", reg[0xbe]); adv7520_comm_power(0, 1); return; } msleep(200); reg[0xB8] = adv7520_read_reg(hclient, 0xB8); DEV_INFO("HDCP: Status reg[0xB8] is %02x\n", reg[0xb8]); if (reg[0xb8] & 0x40) { adv7520_write_reg(hclient, 0x0C, (u8)0x84); DEV_INFO("HDCP: A/V content Encrypted (unmute audio)\n"); external_common_state->hdcp_active = TRUE; } adv7520_comm_power(0, 1); mutex_lock(&hdcp_state_mutex); hdcp_activating = FALSE; mutex_unlock(&hdcp_state_mutex); }
static void adv7525_hdcp_link_work(struct work_struct *work) { u8 reg0xb8 = adv7525_read_reg(hclient_main, 0xb8); if (reg0xb8 & (1 << 6)) { DEV_INFO("%s: HDCP Link OK\n", __func__); mod_timer(&hdcp_link_timer, jiffies + msecs_to_jiffies(2000)); } else { /* clear HDCP request */ adv7525_write_reg_mask(hclient_main, 0xaf, 0x1, 7, 0); adv7525_write_reg_mask(hclient_main, 0xaf, 0x1, 7, 1); DEV_INFO("%s: clear HDCP reg[0xaf]=0x%02x\n", __func__, reg[0xaf]); } }
/* * Write a value to a register on adv7520 device. * Returns zero if successful, or non-zero otherwise. */ static int adv7520_write_reg(struct i2c_client *client, u8 reg, u8 val) { int err; struct i2c_msg msg[1]; unsigned char data[2]; if (!client->adapter) return -ENODEV; if (!atomic_read(&comm_power_on)) { DEV_WARN("%s: WARN: missing GPIO power\n", __func__); return -ENODEV; } msg->addr = client->addr; msg->flags = 0; msg->len = 2; msg->buf = data; data[0] = reg; data[1] = val; err = i2c_transfer(client->adapter, msg, 1); if (err >= 0) return 0; #ifdef PORT_DEBUG DEV_INFO("HDMI[%02x] [W] %02x [%d]\n", reg, val, err); #endif return err; }
bool CGameServer::DispatchGameDBServer(const PacketPtr& PktPtr, KeyRef krSocket) { switch (PktPtr->GetEvent()) { case PAK_EVENT_LINKACK: { m_bGameDBLinked = true; NET_ADDR NetAddr; m_NetworkPtr->GetAddr(krSocket, NetAddr, false); m_pUIHandler->OnHandle(PAK_EVENT_LINK, reinterpret_cast<uintptr_t>(&NetAddr), DATA_INDEX_GAMEDB); LOG_INFO(m_FileLog, TF("[游戏服务器]收到游戏DB服务器注册回复包")); } break; case PAK_EVENT_UPDATEACK: { DEV_INFO(TF("[游戏服务器]收到游戏DB服务器更新回复包")); } break; case PAK_EVENT_UNLINKACK: { m_bGameDBLinked = false; LOG_INFO(m_FileLog, TF("[游戏服务器]收到游戏DB服务器注销回复包")); } break; case PAK_EVENT_LIVEACK: { } break; default: { LOGV_WARN(m_FileLog, TF("[游戏服务器]%p无法识别的游戏DB服务器信令包数据[event=%d]"), krSocket, PktPtr->GetEvent()); } } return true; }
//-------------------------------------- bool CGameServer::OnUdpClose(KeyRef krSocket, LLong) { if (krSocket == m_krUDPService){ m_krUDPService = nullptr; DEV_INFO(TF("[游戏服务器]UDP监听登陆服务器关闭")); } return true; }
int adv7525_i2c_write(struct i2c_client *client, char *buf, int count) { if (count != i2c_master_send(client, buf, count)) { DEV_INFO("%s: i2c write err\n", __func__); return -EBUSY; } return 0; }
static ssize_t external_common_wta_video_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { ssize_t ret = strnlen(buf, PAGE_SIZE); uint32 video_mode; #ifdef CONFIG_FB_MSM_HDMI_COMMON const struct hdmi_disp_mode_timing_type *disp_mode; #endif mutex_lock(&external_common_state_hpd_mutex); if (!external_common_state->hpd_state) { mutex_unlock(&external_common_state_hpd_mutex); DEV_INFO("%s: FAILED: display off or cable disconnected\n", __func__); return ret; } mutex_unlock(&external_common_state_hpd_mutex); video_mode = atoi(buf)-1; kobject_uevent(external_common_state->uevent_kobj, KOBJ_OFFLINE); #ifdef CONFIG_FB_MSM_HDMI_COMMON disp_mode = hdmi_common_get_supported_mode(video_mode); if (!disp_mode) { DEV_INFO("%s: FAILED: mode not supported (%d)\n", __func__, video_mode); return ret; } external_common_state->disp_mode_list.num_of_elements = 1; external_common_state->disp_mode_list.disp_mode_list[0] = video_mode; #elif defined(CONFIG_FB_MSM_TVOUT) external_common_state->tvout_enable(0); external_common_state->video_resolution = video_mode; external_common_state->tvout_enable(1); #endif DEV_DBG("%s: 'mode=%d %s' successful (sending OFF/ONLINE)\n", __func__, video_mode, video_format_2string(video_mode)); kobject_uevent(external_common_state->uevent_kobj, KOBJ_ONLINE); return ret; }
//-------------------------------------- bool CGameServer::OnTcpConnect(UInt uError, KeyRef krConnect) { if (krConnect == m_krConnectCenter) { m_bCenterCnnted = (uError == 0); if (m_bCenterCnnted) { LinkCenterServer(); } else { DEV_INFO(TF("[游戏服务器]连接中心服务器失败%X!"), uError); LOGV_WARN(m_FileLog, TF("[游戏服务器]连接中心服务器失败%X!"), uError); } } else if (krConnect == m_krConnectGameDB) { m_bGameDBCnnted = (uError == 0); if (m_bGameDBCnnted) { LinkGameDBServer(); } else { DEV_INFO(TF("[游戏服务器]连接游戏DB服务器失败%X!"), uError); LOGV_WARN(m_FileLog, TF("[游戏服务器]连接游戏DB服务器失败%X!"), uError); } } return true; }
//-------------------------------------- bool CGameServer::OnTcpAccept(KeyRef krAccept, KeyRef) { if (m_nStatus == STATUSC_RUN) { UShort usPort = 0; CStringKey strAddr; m_NetworkPtr->GetAddr(krAccept, strAddr, usPort); DEV_INFO(TF("[游戏服务器]服务器[%s]:%d连接完成!"), *strAddr, usPort); m_ServerInfo.Incr(); return true; } else { LOGV_WARN(m_FileLog, TF("[游戏服务器]游戏服务器处于暂停状态!")); } return false; }
//-------------------------------------- bool CGameServer::OnTcpClose(KeyRef krSocket, LLong llLiveData) { if (krSocket == m_krConnectCenter) { m_krConnectCenter = nullptr; m_bCenterCnnted = false; m_bCenterLinked = false; m_pUIHandler->OnHandle(PAK_EVENT_UNLINK, 0, DATA_INDEX_CENTER); DEV_INFO(TF("[游戏服务器]连接中心服务器断开")); LOG_INFO(m_FileLog, TF("[游戏服务器]连接中心服务器断开")); } else if (krSocket == m_krConnectGameDB) { m_krConnectGameDB = nullptr; m_bGameDBCnnted = false; m_bGameDBLinked = false; m_pUIHandler->OnHandle(PAK_EVENT_UNLINK, 0, DATA_INDEX_GAMEDB); DEV_INFO(TF("[游戏服务器]连接游戏DB服务器断开")); LOG_INFO(m_FileLog, TF("[游戏服务器]连接游戏DB服务器断开")); } else if (krSocket == m_krListenZone) { m_krListenZone = nullptr; DEV_INFO(TF("[游戏服务器]监听地图服务器关闭")); LOG_INFO(m_FileLog, TF("[游戏服务器]监听地图服务器关闭")); } else if (krSocket == m_krListenGate) { m_krListenGate = nullptr; DEV_INFO(TF("[游戏服务器]监听网关服务器关闭")); LOG_INFO(m_FileLog, TF("[游戏服务器]监听网关服务器关闭")); } else { // 单个服务器断开 switch (llLiveData) { case PAK_TYPE_ZONE: { ServerUnlink<SVR_ZONE_INDEX_MAP, DATA_INDEX_ZONE, INFOI_ZONE>(krSocket, m_ZoneSvrMap); DEV_INFO(TF("[游戏服务器]地图服务器[%p]断开"), krSocket); LOGV_INFO(m_FileLog, TF("游戏服务器]地图服务器[%p]断开"), krSocket); } break; case PAK_TYPE_GATE: { ServerUnlink<SVR_GATE_MAP, DATA_INDEX_GATE, INFOI_GATE>(krSocket, m_GateSvrMap); DEV_INFO(TF("[游戏服务器]网关服务器[%p]断开"), krSocket); LOGV_INFO(m_FileLog, TF("游戏服务器]网关服务器[%p]断开"), krSocket); } break; default: { } } m_ServerInfo.Decr(); } return true; }
bool CGameServer::SelectGame(CPAKLoginSelectGame* pSelect, LLong llParam) { assert(pSelect->GetType() == PAK_TYPE_LOGIN); pSelect->SetType(PAK_TYPE_GAME); // 实际需要按电信或者网通线路PING值为参考来排序 PSORT_RESULT pSortResult = m_SortChain.GetCur(); if (pSortResult->lCount > 0) { Long lIndex = pSortResult->Index(); if ((DataRef)m_pShareGateSvr == pSortResult->Sort[lIndex].drServer) { m_pShareGateSvr->OnShareRoutine(PAK_EVENT_LOGIN_SELECT_GAME, *pSelect, llParam); } else { m_NetworkPtr->SendTo(m_krUDPService, *pSelect, pSortResult->Sort[lIndex].Addr); } DEV_INFO(TF("[游戏服务器]选取第%d个网关服务器"), lIndex); return true; } return false; }
int adv7525_i2c_read(struct i2c_client *client, u8 addr , u8 *buf , int length) { struct i2c_adapter *adap = client->adapter; struct i2c_msg msg[2]; msg[0].addr = client->addr; msg[0].flags = client->flags & I2C_M_TEN; msg[0].len = 1; msg[0].buf = &addr; msg[1].addr = client->addr; msg[1].flags = client->flags & I2C_M_TEN; msg[1].flags |= I2C_M_RD; msg[1].len = length; msg[1].buf = buf; if (i2c_transfer(adap, msg, 2) < 0) { DEV_INFO("%s: i2c read err\n", __func__); return -EBUSY; } return 0; }
//-------------------------------------- bool CGameServer::OnShareRoutine(Int nEvent, CEventBase& EventRef, LLong llParam, CEventQueue::EVENT_TYPE) { assert((m_pConfig->GetLoadServers() & (CServerConfig::CFG_DEFAULT_CENTER|CServerConfig::CFG_DEFAULT_GAMEDB|CServerConfig::CFG_DEFAULT_ZONE|CServerConfig::CFG_DEFAULT_GATE)) != 0); switch (nEvent) { case PAK_EVENT_LINK: { return OnShareLink(EventRef, llParam); } break; case PAK_EVENT_UPDATE: { return OnShareUpdate(EventRef, llParam); } break; //case PAK_EVENT_UNLINK: // 同进程服务器注销, 说明服务停止, 不需要处理 // break; case PAK_EVENT_GAME_ID: { PInt pId = reinterpret_cast<PInt>(llParam); *pId = (Int)m_ServerInfo.usId; } break; case PAK_EVENT_LOGIN_SELECT_GAME: { CPAKLoginSelectGame* pSelect = static_cast<CPAKLoginSelectGame*>(&EventRef); if (SelectGame(pSelect, llParam) == false) { pSelect->SetAck(LOGIN_ERROR_NONE_GATE); reinterpret_cast<ICommonServer*>(llParam)->OnShareRoutine(PAK_EVENT_LOGIN_SELECT_GAME, *pSelect); DEV_INFO(TF("[游戏服务器]同进程游戏服务器收到客户端选择游戏服务器请求, 但是没有网关服务器")); } } break; default: { LOGV_WARN(m_FileLog, TF("[游戏服务器]同进程服务器无法识别的信令包数据[event=%d]"), nEvent); assert(0); } } return true; }
void adv7525_cec_init(void) { int i; u16 phy_addr = hdmi_common_get_phy_addr(); /* CEC Clock Timing Setting: 1.2MHz */ for (i = 0; i < ARRAY_SIZE(cec_clk_table_1_2_mhz); i++) adv7525_write_reg(hclient_cec, cec_clk_table_1_2_mhz[i].reg_addr, cec_clk_table_1_2_mhz[i].reg_data); /* Initial cecdata structure */ cecdata.logical_addr = hdmi_cec_get_logical_addr(); cecdata.hdr_directly = cecdata.logical_addr << 4 | 0x0; cecdata.hdr_broadcast = cecdata.logical_addr << 4 | 0xf; cecdata.physical_addr[0] = (u8)(phy_addr >> 8); cecdata.physical_addr[1] = (u8)(phy_addr & 0x0f) ; DEV_INFO("logcal addr: 0x%x, physical addr: 0x%x\n", cecdata.logical_addr, phy_addr); /* CEC Rx Setting init */ adv7525_write_reg(hclient_cec, 0x4a, 0); adv7525_write_reg(hclient_cec, 0x4c, (0xf << 4 | cecdata.logical_addr)); }
/* Change HDMI state */ static void change_hdmi_state(int online) { if (!external_common_state) return; mutex_lock(&external_common_state_hpd_mutex); external_common_state->hpd_state = online; mutex_unlock(&external_common_state_hpd_mutex); if (!external_common_state->uevent_kobj) return; if (online) { kobject_uevent(external_common_state->uevent_kobj, KOBJ_ONLINE); switch_set_state(&external_common_state->sdev, 1); } else { kobject_uevent(external_common_state->uevent_kobj, KOBJ_OFFLINE); switch_set_state(&external_common_state->sdev, 0); } DEV_INFO("adv7520_uevent: %d [suspend# %d]\n", online, suspend_count); }
static void adv7520_close_hdcp_link(void) { if (!external_common_state->hdcp_active && !hdcp_activating) return; DEV_INFO("HDCP: Close link\n"); reg[0xD5] = adv7520_read_reg(hclient, 0xD5); reg[0xD5] &= 0xFE; adv7520_write_reg(hclient, 0xD5, (u8)reg[0xD5]); reg[0x16] = adv7520_read_reg(hclient, 0x16); reg[0x16] &= 0xFE; adv7520_write_reg(hclient, 0x16, (u8)reg[0x16]); /* UnMute Audio */ adv7520_write_reg(hclient, 0x0C, (u8)0x84); external_common_state->hdcp_active = FALSE; mutex_lock(&hdcp_state_mutex); hdcp_activating = FALSE; mutex_unlock(&hdcp_state_mutex); }
static void hdmi_tx_hpd_state_work(struct work_struct *work) { u32 hpd_state = false; struct hdmi_tx_ctrl *hdmi_ctrl = NULL; struct hdmi_tx_io_data *io = NULL; hdmi_ctrl = container_of(work, struct hdmi_tx_ctrl, hpd_state_work); if (!hdmi_ctrl || !hdmi_ctrl->hpd_initialized) { DEV_DBG("%s: invalid input\n", __func__); return; } io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO]; DEV_DBG("%s: Got HPD interrupt\n", __func__); hpd_state = (HDMI_REG_R(io->base, HDMI_HPD_INT_STATUS) & BIT(1)) >> 1; mutex_lock(&hdmi_ctrl->mutex); if ((hdmi_ctrl->hpd_prev_state != hdmi_ctrl->hpd_state) || (hdmi_ctrl->hpd_state != hpd_state)) { hdmi_ctrl->hpd_state = hpd_state; hdmi_ctrl->hpd_prev_state = hdmi_ctrl->hpd_state; hdmi_ctrl->hpd_stable = 0; DEV_DBG("%s: state not stable yet, wait again (%d|%d|%d)\n", __func__, hdmi_ctrl->hpd_prev_state, hdmi_ctrl->hpd_state, hpd_state); mutex_unlock(&hdmi_ctrl->mutex); mod_timer(&hdmi_ctrl->hpd_state_timer, jiffies + HZ/2); return; } if (hdmi_ctrl->hpd_stable) { mutex_unlock(&hdmi_ctrl->mutex); DEV_DBG("%s: no more timer, depending on IRQ now\n", __func__); return; } hdmi_ctrl->hpd_stable = 1; DEV_INFO("HDMI HPD: event detected\n"); /* *todo: Revisit cable chg detected condition when HPD support is ready */ hdmi_ctrl->hpd_cable_chg_detected = false; mutex_unlock(&hdmi_ctrl->mutex); if (hpd_state) { DEV_INFO("HDMI HPD: sense CONNECTED: send ONLINE\n"); kobject_uevent(hdmi_ctrl->kobj, KOBJ_ONLINE); switch_set_state(&hdmi_ctrl->sdev, 1); DEV_INFO("%s: Hdmi state switch to %d\n", __func__, hdmi_ctrl->sdev.state); } else { DEV_INFO("HDMI HPD: sense DISCONNECTED: send OFFLINE\n"); kobject_uevent(hdmi_ctrl->kobj, KOBJ_OFFLINE); switch_set_state(&hdmi_ctrl->sdev, 0); DEV_INFO("%s: Hdmi state switch to %d\n", __func__, hdmi_ctrl->sdev.state); } /* Set IRQ for HPD */ HDMI_REG_W(io->base, HDMI_HPD_INT_CTRL, 4 | (hpd_state ? 0 : 2)); } /* hdmi_tx_hpd_state_work */
void adv7525_cec_rx_handle(u8 *rxbuf) { u8 txbuf[16] = {0}; int tx_length = 0; DEV_INFO("%s: Opcode=0x%x, Data1=0x%x\n", __func__, rxbuf[1], rxbuf[2]); switch (rxbuf[1]) { case CEC_OPCODE_USER_CONTROL_PRESSED: if (rxbuf[2]) input_report_key(dd->input, rxbuf[2], 1); else input_report_key(dd->input, 0x2b, 1); /* Select key */ break; case CEC_OPCODE_USER_CONTROL_RELEASED: if (rxbuf[2]) input_report_key(dd->input, rxbuf[2], 0); else input_report_key(dd->input, 0x2b, 0); break; case CEC_OPCODE_PLAY: switch (rxbuf[2]) { case 0x24: case 0x25: input_report_key(dd->input, 0x46, 1); input_report_key(dd->input, 0x46, 0); break; default: break; } break; case CEC_OPCODE_DECK_CONTROL: switch (rxbuf[2]) { case 0x1: input_report_key(dd->input, 0x49, 1); input_report_key(dd->input, 0x49, 0); break; case 0x2: input_report_key(dd->input, 0x48, 1); input_report_key(dd->input, 0x48, 0); break; case 0x3: /* stop */ input_report_key(dd->input, 0x46, 1); input_report_key(dd->input, 0x46, 0); break; default: break; } break; case CEC_OPCODE_GIVE_OSD_NAME: txbuf[1] = cecdata.hdr_directly; txbuf[2] = CEC_OPCODE_SET_OSD_NAME; txbuf[3] = 'A'; txbuf[4] = 'c'; txbuf[5] = 'e'; txbuf[6] = 'r'; txbuf[7] = ' '; txbuf[8] = 'S'; txbuf[9] = '3'; txbuf[10] = '0'; txbuf[11] = '0'; tx_length = 11; break; case CEC_OPCODE_GIVE_DEVICE_VENDOR_ID: txbuf[1] = cecdata.hdr_broadcast; txbuf[2] = CEC_OPCODE_DEVICE_VENDOR_ID; txbuf[3] = 0x00; txbuf[4] = 0x00; txbuf[5] = 0xE2; tx_length = 5; break; case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS: txbuf[1] = cecdata.hdr_directly; txbuf[2] = CEC_OPCODE_REPORT_POWER_STATUS; txbuf[3] = 0x00; tx_length = 3; break; case CEC_OPCODE_GET_CEC_VERSION: txbuf[1] = cecdata.hdr_directly; txbuf[2] = CEC_OPCODE_CEC_VERSION; txbuf[3] = 0x04; tx_length = 3; break; case CEC_OPCODE_SET_STREAM_PATH: case CEC_OPCODE_REQUEST_ACTIVE_SOURCE: txbuf[1] = cecdata.hdr_broadcast; txbuf[2] = CEC_OPCODE_ACTIVE_SOURCE; txbuf[3] = cecdata.physical_addr[0]; txbuf[4] = cecdata.physical_addr[1]; tx_length = 4; break; case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS: txbuf[1] = cecdata.hdr_broadcast; txbuf[2] = CEC_OPCODE_REPORT_PHYSICAL_ADDRESS; txbuf[3] = cecdata.physical_addr[0]; txbuf[4] = cecdata.physical_addr[1]; txbuf[5] = type_playback_device; tx_length = 5; break; case CEC_OPCODE_GIVE_DECK_STATUS: txbuf[1] = cecdata.hdr_directly; txbuf[2] = CEC_OPCODE_DECK_STATUS; txbuf[3] = 0x01; tx_length = 3; break; case CEC_OPCODE_MENU_REQUEST: txbuf[1] = cecdata.hdr_directly; txbuf[2] = CEC_OPCODE_MENU_STATUS; txbuf[3] = 0x01; tx_length = 3; break; default: break; } if (tx_length != 0) { adv7525_i2c_write(hclient_cec, txbuf, tx_length+1); adv7525_write_reg(hclient_cec, 0x10, tx_length); adv7525_write_reg(hclient_cec, 0x11, 0x1); } }