int rk610_hdmi_sys_read_edid(int block, unsigned char *buff) { char value; int count, rc = HDMI_ERROR_EDID; char hdmi_status = 0; // Config DDC bus clock: ddc_clk = reg_clk/4*(reg 0x4c 0x4b) // when reg00 select reg_clk equal to sys_clk which is equal // to i2s clk, it gernerally is 11.2896MHz. count = SYSCLK/(DDC_CLK*4); HDMIWrReg(DDC_CLK_L, count & 0xFF); HDMIWrReg(DDC_CLK_H, (count >> 8) & 0xFF); // Enable EDID Interrupt // edid_ready = 0; atomic_set(&edid_ready, 0); value = 0; rk610_hdmi_i2c_read_reg(INTERRUPT_MASK1, &value); value |= m_INT_EDID_READY; HDMIWrReg(INTERRUPT_MASK1, value); // Reset FIFO offset HDMIWrReg(EDID_FIFO_OFFSET, 0); // Set EDID read addr. HDMIWrReg(EDID_WORD_ADDR, (block%2) * 0x80); HDMIWrReg(EDID_SEGMENT_POINTER, block/2); count = 0; while(count++ < 10) { #ifdef HDMI_USE_IRQ value = atomic_read(&edid_ready); #else msleep(10); rk610_hdmi_i2c_read_reg(INTERRUPT_STATUS1, &hdmi_status); value = (hdmi_status & m_INT_EDID_READY); #endif if(value) { for(value = 0; value < 128; value++) rk610_hdmi_i2c_read_reg(EDID_FIFO_ADDR, buff + value); rc = HDMI_ERROR_SUCESS; break; } msleep(100); } // Disable EDID interrupt. value = 0; rk610_hdmi_i2c_read_reg(INTERRUPT_MASK1, &value); value &= ~m_INT_EDID_READY; HDMIWrReg(INTERRUPT_MASK1, value); return rc; }
int rk610_hdmi_sys_detect_hpd(void) { char hdmi_status = 0; #ifdef HDMI_USE_IRQ rk610_hdmi_i2c_read_reg(INTERRUPT_STATUS1, &hdmi_status); HDMIWrReg(INTERRUPT_STATUS1, hdmi_status); #endif hdmi_status = 0; rk610_hdmi_i2c_read_reg(HDMI_STATUS, &hdmi_status); // printk("%s value is %02x\n", __FUNCTION__, hdmi_status); if(hdmi_status) return HDMI_HPD_ACTIVED; else return HDMI_HPD_REMOVED; }
int rk610_hdmi_sys_detect_hpd(struct hdmi *hdmi, int *hpdstatus) { char hdmi_status = 0; #ifdef HDMI_USE_IRQ rk610_hdmi_i2c_read_reg(INTERRUPT_STATUS1, &hdmi_status); HDMIWrReg(INTERRUPT_STATUS1, hdmi_status); #endif hdmi_status = 0; rk610_hdmi_i2c_read_reg(HDMI_STATUS, &hdmi_status); // printk("%s value is %02x\n", __FUNCTION__, hdmi_status); if(hdmi_status) *hpdstatus = HDMI_RECEIVER_ACTIVE; else *hpdstatus = HDMI_RECEIVER_REMOVE; return HDMI_ERROR_SUCESS; }
void rk610_hdmi_interrupt() { char interrupt = 0; if(rk610_hdmi_i2c_read_reg(INTERRUPT_STATUS1, &interrupt)) return; HDMIWrReg(INTERRUPT_STATUS1, interrupt); hdmi_dbg(rk610_hdmi->hdmi->dev, "%s interrupt %02x\n", __FUNCTION__, interrupt); if(interrupt) HDMIWrReg(INTERRUPT_STATUS1, interrupt); if(interrupt & m_INT_HOTPLUG) hdmi_changed(rk610_hdmi->hdmi, 0); if(interrupt & m_INT_EDID_READY) edid_ready = 1; }
void rk610_hdmi_sys_enalbe_output(int enable) { char mutestatus = 0; if(enable) { rk610_hdmi_i2c_read_reg(AV_MUTE, &mutestatus); if(mutestatus && (m_AUDIO_MUTE | m_VIDEO_BLACK)) { HDMIWrReg(AV_MUTE, v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0)); HDMIWrReg(SYS_CTRL, v_REG_CLK_SOURCE_IIS | v_PWR_ON | v_INT_POL_HIGH); HDMIWrReg(SYS_CTRL, v_REG_CLK_SOURCE_IIS | v_PWR_OFF | v_INT_POL_HIGH); HDMIWrReg(SYS_CTRL, v_REG_CLK_SOURCE_IIS | v_PWR_ON | v_INT_POL_HIGH); if(hdmi->hdcp_cb) hdmi->hdcp_cb(); } } else { HDMIWrReg(AV_MUTE, v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1)); } }
void rk610_hdmi_interrupt() { char interrupt = 0; if(rk610_hdmi_i2c_read_reg(INTERRUPT_STATUS1, &interrupt)) return; HDMIWrReg(INTERRUPT_STATUS1, interrupt); if(interrupt) HDMIWrReg(INTERRUPT_STATUS1, interrupt); if(interrupt & m_INT_HOTPLUG) { hdmi_dbg(hdmi->dev, "%s interrupt %02x\n", __FUNCTION__, interrupt); if(hdmi->state == HDMI_SLEEP) hdmi->state = WAIT_HOTPLUG; queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10)); } else if(interrupt & m_INT_EDID_READY) { atomic_set(&edid_ready, 1); } }
int rk610_hdmi_sys_config_video(struct hdmi *hdmi, int vic, int input_color, int output_color) { char value; struct fb_videomode *mode; // Diable HDCP if(rk610_hdmi->hdcp_power_off_cb) rk610_hdmi->hdcp_power_off_cb(); // Diable video and audio output HDMIWrReg(AV_MUTE, v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1)); // Input video mode is SDR RGB24bit, Data enable signal from external HDMIWrReg(VIDEO_CONTRL1, v_VIDEO_INPUT_FORMAT(VIDEO_INPUT_SDR_RGB444) | v_DE_EXTERNAL); HDMIWrReg(VIDEO_CONTRL2, v_VIDEO_INPUT_BITS(VIDEO_INPUT_8BITS) | (output_color & 0xFF)); // Set HDMI Mode HDMIWrReg(HDCP_CTRL, v_HDMI_DVI(hdmi->edid.is_hdmi)); // Enable or disalbe color space convert if(input_color != output_color) { value = v_SOF_DISABLE | v_CSC_ENABLE; } else value = v_SOF_DISABLE; HDMIWrReg(VIDEO_CONTRL3, value); #if 1 HDMIWrReg(VIDEO_TIMING_CTL, 0); mode = (struct fb_videomode *)ext_hdmi_vic_to_videomode(vic); if(mode == NULL) { hdmi_dbg(hdmi->dev, "[%s] not found vic %d\n", __FUNCTION__, vic); return -ENOENT; } rk610_hdmi->frequency = mode->pixclock; #else // Set ext video value = v_EXTERANL_VIDEO(1) | v_INETLACE(mode->vmode); if(mode->sync & FB_SYNC_HOR_HIGH_ACT) value |= v_HSYNC_POLARITY(1); if(mode->sync & FB_SYNC_VERT_HIGH_ACT) value |= v_VSYNC_POLARITY(1); HDMIWrReg(VIDEO_TIMING_CTL, value); value = mode->left_margin + mode->xres + mode->right_margin + mode->hsync_len; HDMIWrReg(VIDEO_EXT_HTOTAL_L, value & 0xFF); HDMIWrReg(VIDEO_EXT_HTOTAL_H, (value >> 8) & 0xFF); value = mode->left_margin + mode->right_margin + mode->hsync_len; HDMIWrReg(VIDEO_EXT_HBLANK_L, value & 0xFF); HDMIWrReg(VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF); value = mode->left_margin + mode->hsync_len; HDMIWrReg(VIDEO_EXT_HDELAY_L, value & 0xFF); HDMIWrReg(VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF); value = mode->hsync_len; HDMIWrReg(VIDEO_EXT_HDURATION_L, value & 0xFF); HDMIWrReg(VIDEO_EXT_HDURATION_H, (value >> 8) & 0xFF); value = mode->upper_margin + mode->yres + mode->lower_margin + mode->vsync_len; HDMIWrReg(VIDEO_EXT_VTOTAL_L, value & 0xFF); HDMIWrReg(VIDEO_EXT_VTOTAL_H, (value >> 8) & 0xFF); value = mode->upper_margin + mode->vsync_len + mode->lower_margin; HDMIWrReg(VIDEO_EXT_VBLANK, value & 0xFF); value = mode->upper_margin + mode->vsync_len; HDMIWrReg(VIDEO_EXT_VDELAY, value & 0xFF); value = mode->vsync_len; HDMIWrReg(VIDEO_EXT_VDURATION, value & 0xFF); #endif if(hdmi->edid.is_hdmi) { rk610_hdmi_config_avi(vic, output_color); hdmi_dbg(hdmi->dev, "[%s] sucess output HDMI.\n", __FUNCTION__); } else { hdmi_dbg(hdmi->dev, "[%s] sucess output DVI.\n", __FUNCTION__); } // Power on TMDS HDMIWrReg(PHY_PRE_EMPHASIS, v_PRE_EMPHASIS(0) | v_TMDS_PWRDOWN(0)); // TMDS power on // Enable TMDS value = 0; rk610_hdmi_i2c_read_reg(PHY_DRIVER, &value); value |= v_TX_ENABLE(1); HDMIWrReg(PHY_DRIVER, value); return 0; }