static int lcdc_unblank(struct msm_panel_data *fb_panel) { struct mdp_lcdc_info *lcdc = panel_to_lcdc(fb_panel); struct msm_lcdc_panel_ops *panel_ops = lcdc->pdata->panel_ops; HDMI_DBG("%s\n", __func__); #if 0 HDMI_DBG("%s: enable clocks\n", __func__); clk_enable(lcdc->mdp_clk); clk_enable(lcdc->pclk); clk_enable(lcdc->pad_pclk); panel_ops->unblank(panel_ops); mdp_writel(lcdc->mdp, 1, MDP_LCDC_EN); atomic_set(&lcdc->blank_count, 1); #else lcdc_enable_video(); /* TODO: need pre-test to see if it make any influence to HDCP, * if ebi1_clk enabled here. */ panel_ops->unblank(panel_ops); #endif return 0; }
/* FIXME: arrange the clock manipulating to proper place, integrate with the counter of fb_hdmi */ int lcdc_enable_video(void) { //struct mdp_lcdc_info *lcdc = panel_to_lcdc(fb_panel); struct mdp_lcdc_info *lcdc = _lcdc; struct msm_lcdc_panel_ops *panel_ops = lcdc->pdata->panel_ops; mutex_lock(&lcdc->blank_lock); if (atomic_read(&lcdc->blank_count)) goto end_enable_video; HDMI_DBG("%s: enable clocks\n", __func__); clk_enable(lcdc->mdp_clk); clk_enable(lcdc->pclk); clk_enable(lcdc->pad_pclk); /* TODO: need pre-test to see if it make any influence to HDCP, * if ebi1_clk doesn't enabled here. */ //panel_ops->unblank(panel_ops); mdp_writel(lcdc->mdp, 1, MDP_LCDC_EN); atomic_inc(&lcdc->blank_count); HDMI_DBG("%s, blank_count=%d\n", __func__, atomic_read(&lcdc->blank_count)); end_enable_video: mutex_unlock(&lcdc->blank_lock); return 0; }
static int lcdc_blank(struct msm_panel_data *fb_panel) { struct mdp_lcdc_info *lcdc = panel_to_lcdc(fb_panel); //struct msm_lcdc_panel_ops *panel_ops = lcdc->pdata->panel_ops; #if 0 mutex_lock(&lcdc->blank_lock); if (atomic_read(&lcdc->blank_count) == 0) goto blank_done; if (atomic_dec_return(&lcdc->blank_count) == 0) { HDMI_DBG("%s: disable clocks\n", __func__); panel_ops->blank(panel_ops); mdp_writel(lcdc->mdp, 0, MDP_LCDC_EN); clk_disable(lcdc->pclk); clk_disable(lcdc->pad_pclk); clk_disable(lcdc->mdp_clk); } blank_done: mutex_unlock(&lcdc->blank_lock); HDMI_DBG("%s, blank_count=%d\n", __func__, atomic_read(&lcdc->blank_count)); #else lcdc_disable_video(); #endif return 0; }
static void OnDownstreamRxPoweredUp(struct hdmi_info *hdmi) { HDMI_DBG("%s\n", __func__); dsRxPoweredUp = true; HotPlugService(hdmi); #ifdef CONFIG_HTC_HEADSET_MGR /* send cable in event */ switch_send_event(BIT_HDMI_CABLE, 1); HDMI_DBG("Cable inserted.\n"); #endif pvid_mode = vid_mode; hdmi_active9022_dup(hdmi->client); }
bool ReleaseDDC(struct hdmi_info *hdmi, u8 SysCtrlRegVal) { u8 DDCReqTimeout = T_DDC_ACCESS, TPI_ControlImage; HDMI_DBG("%s\n", __func__); /* Just to be sure bits [2:1] are 0 before it is written */ SysCtrlRegVal &= ~(0x6); /* Loop till 0x1A[1] reads "0" */ while (DDCReqTimeout--) { /* Cannot use ReadClearWriteTPI() here. A read of * TPI_SYSTEM_CONTROL is invalid while DDC is granted. * Doing so will return 0xFF, and cause an invalid value to be * written back. */ /* 0x1A[2:1] = "0" - release the DDC bus */ //ReadClearWriteTPI(TPI_SYSTEM_CONTROL,BITS_2_1); hdmi_write_byte(hdmi->client, TPI_SYSTEM_CONTROL, SysCtrlRegVal); TPI_ControlImage = hdmi_read(hdmi->client, TPI_SYSTEM_CONTROL); /* When 0x1A[2:1] read "0" */ if (!(TPI_ControlImage & 0x6)) return true; } /* Failed to release DDC bus control */ return false; }
bool GetDDC_Access(struct hdmi_info *hdmi, u8* SysCtrlRegVal) { u8 sysCtrl, TPI_ControlImage, DDCReqTimeout = T_DDC_ACCESS; HDMI_DBG("%s\n", __func__); /* Read and store original value. Will be passed into ReleaseDDC() */ sysCtrl = hdmi_read(hdmi->client, TPI_SYSTEM_CONTROL); *SysCtrlRegVal = sysCtrl; sysCtrl |= BIT_DDC_BUS_REQ; hdmi_write_byte(hdmi->client, TPI_SYSTEM_CONTROL, sysCtrl); /* Loop till 0x1A[1] reads "1" */ while (DDCReqTimeout--) { TPI_ControlImage = hdmi_read(hdmi->client, TPI_SYSTEM_CONTROL); /* When 0x1A[1] reads "1" */ if (TPI_ControlImage & BIT_DDC_BUS_GRANT) { sysCtrl |= BIT_DDC_BUS_GRANT; /* lock host DDC bus access (0x1A[2:1] = 11) */ hdmi_write_byte(hdmi->client, TPI_SYSTEM_CONTROL, sysCtrl); return true; } /* 0x1A[2] = "1" - Requst the DDC bus */ hdmi_write_byte(hdmi->client, TPI_SYSTEM_CONTROL, sysCtrl); mdelay(200); } /* Failure... restore original value. */ hdmi_write_byte(hdmi->client, TPI_SYSTEM_CONTROL, sysCtrl); return false; }
int lcdc_disable_video(void) { struct mdp_lcdc_info *lcdc = _lcdc; struct msm_lcdc_panel_ops *panel_ops = lcdc->pdata->panel_ops; mutex_lock(&lcdc->blank_lock); if (atomic_read(&lcdc->blank_count) == 0) goto disable_video_done; if (atomic_dec_return(&lcdc->blank_count) == 0) { HDMI_DBG("%s: disable clocks\n", __func__); panel_ops->blank(panel_ops); mdp_writel(lcdc->mdp, 0, MDP_LCDC_EN); clk_disable(lcdc->pclk); clk_disable(lcdc->pad_pclk); clk_disable(lcdc->mdp_clk); } disable_video_done: mutex_unlock(&lcdc->blank_lock); HDMI_DBG("%s, blank_count=%d\n", __func__, atomic_read(&lcdc->blank_count)); return 0; }
static void suc_hdmi_gpio_off(void) { int i = 0; HDMI_DBG("%s\n", __func__); config_gpio_table(hdmi_gpio_off_table, ARRAY_SIZE(hdmi_gpio_off_table)); for (i = SUPERSONIC_LCD_R0; i <= SUPERSONIC_LCD_R4; i++) gpio_set_value(i, 0); for (i = SUPERSONIC_LCD_G0; i <= SUPERSONIC_LCD_G5; i++) gpio_set_value(i, 0); for (i = SUPERSONIC_LCD_B0; i <= SUPERSONIC_LCD_DE; i++) gpio_set_value(i, 0); }
static int lcdc_suspend(struct msm_panel_data *fb_panel) { struct mdp_lcdc_info *lcdc = panel_to_lcdc(fb_panel); struct msm_lcdc_panel_ops *panel_ops = lcdc->pdata->panel_ops; //pr_info("%s: suspending\n", __func__); HDMI_DBG("%s\n", __func__); if (panel_ops->uninit) panel_ops->uninit(panel_ops); lcdc_disable_video(); return 0; }
static int hdmi_power(int on) { HDMI_DBG("%s(%d)\n", __func__, on); switch(on) { /* Power on/off sequence for normal or D2 sleep mode */ case 0: gpio_set_value(HDMI_RST, 0); msleep(2); gpio_set_value(V_HDMI_3V3_EN, 0); gpio_set_value(V_VGA_5V_SIL9022A_EN, 0); msleep(2); gpio_set_value(V_HDMI_1V2_EN, 0); break; case 1: gpio_set_value(V_HDMI_1V2_EN, 1); msleep(2); gpio_set_value(V_VGA_5V_SIL9022A_EN, 1); gpio_set_value(V_HDMI_3V3_EN, 1); msleep(2); gpio_set_value(HDMI_RST, 1); msleep(2); break; /* Power on/off sequence for D3 sleep mode */ case 2: gpio_set_value(V_HDMI_3V3_EN, 0); break; case 3: gpio_set_value(HDMI_RST, 0); msleep(2); gpio_set_value(V_HDMI_3V3_EN, 1); gpio_set_value(V_VGA_5V_SIL9022A_EN, 1); msleep(50); gpio_set_value(HDMI_RST, 1); msleep(10); break; case 4: gpio_set_value(V_VGA_5V_SIL9022A_EN, 0); break; case 5: gpio_set_value(V_VGA_5V_SIL9022A_EN, 1); break; default: return -EINVAL; } return 0; }
static void tpi_clear_pending_event(struct hdmi_info *hdmi) { int retry = 100; if (hdmi->sleeping == SLEEP) return; while (retry--) { hdmi_write_byte(hdmi->client, 0x3c, 1); hdmi_write_byte(hdmi->client, 0x3d, 1); if (hdmi_read(hdmi->client, 0x3d) & 0x01) msleep(1); else break; } if (retry < 19) HDMI_DBG("%s: retry=%d\n", __func__, 19 - retry); }
static int lcdc_resume(struct msm_panel_data *fb_panel) { struct mdp_lcdc_info *lcdc = panel_to_lcdc(fb_panel); struct msm_lcdc_panel_ops *panel_ops = lcdc->pdata->panel_ops; //pr_info("%s: resuming\n", __func__); HDMI_DBG("%s\n", __func__); if (panel_ops->init) { if (panel_ops->init(panel_ops) < 0) printk(KERN_ERR "LCD init fail!\n"); } return 0; }
void EnableTMDS(struct hdmi_info *hdmi) { #if 1 /* 0x1A[4] = 0 */ ReadClearWriteTPI(hdmi, TPI_SYSTEM_CONTROL, BIT_TMDS_OUTPUT); if (edid_check_sink_type(hdmi)) hdmi_write_byte(hdmi->client, 0x26, hdmi_read(hdmi->client, 0x26) & ~0x10); #else u8 val; struct i2c_client *client = hdmi->i2c_client; val = hdmi_read(client, TPI_SYSTEM_CONTROL); hdmi_write_byte(client, TPI_SYSTEM_CONTROL, val & ~BIT_TMDS_OUTPUT); HDMI_DBG("%s, reg 0x1a: %02x->%02x\n", __func__, val, val & ~BIT_TMDS_OUTPUT); #endif }
////////////////////////////////////////////////////////////////////////////// // FUNCTION : EnableInterrupts() // PURPOSE : Enable the interrupts specified in the input parameter // INPUT PARAMS : A bit pattern with "1" for each interrupt that needs to be // set in the Interrupt Enable Register (TPI offset 0x3C) // OUTPUT PARAMS : void // GLOBALS USED : None // RETURNS : TRUE ////////////////////////////////////////////////////////////////////////////// bool tpi_enable_interrupts(struct hdmi_info *hdmi, u8 Interrupt_Pattern) { HDMI_DBG("%s, reg=%02x, pat=%02x\n", __func__, TPI_INTERRUPT_EN, Interrupt_Pattern); ReadSetWriteTPI(hdmi, TPI_INTERRUPT_EN, Interrupt_Pattern); return true; }
static void suc_hdmi_gpio_on(void) { HDMI_DBG("%s\n", __func__); config_gpio_table(hdmi_gpio_on_table, ARRAY_SIZE(hdmi_gpio_on_table)); }
static void OnDownstreamRxPoweredDown(struct hdmi_info *hdmi) { HDMI_DBG("%s\n", __func__); dsRxPoweredUp = false; hdcp_off(hdmi); }
static int lcdc_adjust_timing(struct msm_panel_data *fb_panel, struct msm_lcdc_timing *timing, u32 xres, u32 yres) { struct mdp_lcdc_info *lcdc = panel_to_lcdc(fb_panel); unsigned int hsync_period; unsigned int hsync_start_x; unsigned int hsync_end_x; unsigned int vsync_period; unsigned int display_vstart; unsigned int display_vend; uint32_t dma_cfg; clk_set_rate(lcdc->pclk, timing->clk_rate); clk_set_rate(lcdc->pad_pclk, timing->clk_rate); HDMI_DBG("%s, clk=%d, xres=%d, yres=%d,\n", __func__, clk_get_rate(lcdc->pclk), xres, yres); hsync_period = (timing->hsync_pulse_width + timing->hsync_back_porch + xres + timing->hsync_front_porch); hsync_start_x = (timing->hsync_pulse_width + timing->hsync_back_porch); hsync_end_x = hsync_period - timing->hsync_front_porch - 1; vsync_period = (timing->vsync_pulse_width + timing->vsync_back_porch + yres + timing->vsync_front_porch); vsync_period *= hsync_period; display_vstart = timing->vsync_pulse_width + timing->vsync_back_porch; display_vstart *= hsync_period; display_vstart += timing->hsync_skew; display_vend = timing->vsync_front_porch * hsync_period; display_vend = vsync_period - display_vend + timing->hsync_skew - 1; /* register values we pre-compute at init time from the timing * information in the panel info */ lcdc->parms.hsync_ctl = (((hsync_period & 0xfff) << 16) | (timing->hsync_pulse_width & 0xfff)); lcdc->parms.vsync_period = vsync_period & 0xffffff; lcdc->parms.vsync_pulse_width = (timing->vsync_pulse_width * hsync_period) & 0xffffff; lcdc->parms.display_hctl = (((hsync_end_x & 0xfff) << 16) | (hsync_start_x & 0xfff)); lcdc->parms.display_vstart = display_vstart & 0xffffff; lcdc->parms.display_vend = display_vend & 0xffffff; lcdc->parms.hsync_skew = timing->hsync_skew & 0xfff; lcdc->parms.polarity = ((timing->hsync_act_low << 0) | (timing->vsync_act_low << 1) | (timing->den_act_low << 2)); lcdc->parms.clk_rate = timing->clk_rate; mdp_writel(lcdc->mdp, lcdc->parms.hsync_ctl, MDP_LCDC_HSYNC_CTL); mdp_writel(lcdc->mdp, lcdc->parms.vsync_period, MDP_LCDC_VSYNC_PERIOD); mdp_writel(lcdc->mdp, lcdc->parms.vsync_pulse_width, MDP_LCDC_VSYNC_PULSE_WIDTH); mdp_writel(lcdc->mdp, lcdc->parms.display_hctl, MDP_LCDC_DISPLAY_HCTL); mdp_writel(lcdc->mdp, lcdc->parms.display_vstart, MDP_LCDC_DISPLAY_V_START); mdp_writel(lcdc->mdp, lcdc->parms.display_vend, MDP_LCDC_DISPLAY_V_END); mdp_writel(lcdc->mdp, lcdc->parms.hsync_skew, MDP_LCDC_HSYNC_SKEW); mdp_writel(lcdc->mdp, 0, MDP_LCDC_BORDER_CLR); mdp_writel(lcdc->mdp, 0x0, MDP_LCDC_UNDERFLOW_CTL); mdp_writel(lcdc->mdp, 0, MDP_LCDC_ACTIVE_HCTL); mdp_writel(lcdc->mdp, 0, MDP_LCDC_ACTIVE_V_START); mdp_writel(lcdc->mdp, 0, MDP_LCDC_ACTIVE_V_END); mdp_writel(lcdc->mdp, lcdc->parms.polarity, MDP_LCDC_CTL_POLARITY); printk("solomon: polarity=%04x\n", mdp_readl(lcdc->mdp, MDP_LCDC_CTL_POLARITY)); /* config the dma_p block that drives the lcdc data */ mdp_writel(lcdc->mdp, lcdc->fb_start, MDP_DMA_P_IBUF_ADDR); mdp_writel(lcdc->mdp, (((yres & 0x7ff) << 16) | (xres & 0x7ff)), MDP_DMA_P_SIZE); /* TODO: pull in the bpp info from somewhere else? */ mdp_writel(lcdc->mdp, xres * 2, MDP_DMA_P_IBUF_Y_STRIDE); mdp_writel(lcdc->mdp, 0, MDP_DMA_P_OUT_XY); dma_cfg = (DMA_PACK_ALIGN_LSB | DMA_PACK_PATTERN_RGB | DMA_DITHER_EN); dma_cfg |= DMA_OUT_SEL_LCDC; dma_cfg |= DMA_IBUF_FORMAT_RGB565; dma_cfg |= DMA_DSTC0G_8BITS | DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS; mdp_writel(lcdc->mdp, dma_cfg, MDP_DMA_P_CONFIG); return 0; }