/* voltage mode and pre emphasis cfg */ void mdss_edp_phy_vm_pe_init(unsigned char *edp_base) { /* EDP_PHY_EDPPHY_GLB_VM_CFG0 */ edp_write(edp_base + 0x510, 0x3); /* vm only */ /* EDP_PHY_EDPPHY_GLB_VM_CFG1 */ edp_write(edp_base + 0x514, 0x64); /* EDP_PHY_EDPPHY_GLB_MISC9 */ edp_write(edp_base + 0x518, 0x6c); }
/* voltage mode and pre emphasis cfg */ void mdss_edp_phy_vm_pe_init(struct mdss_edp_drv_pdata *ep) { /* EDP_PHY_EDPPHY_GLB_VM_CFG0 */ edp_write(ep->base + 0x510, 0x3); /* vm only */ /* EDP_PHY_EDPPHY_GLB_VM_CFG1 */ edp_write(ep->base + 0x514, 0x64); /* EDP_PHY_EDPPHY_GLB_MISC9 */ edp_write(ep->base + 0x518, 0x6c); }
irqreturn_t edp_isr(int irq, void *ptr) { struct mdss_edp_drv_pdata *ep = (struct mdss_edp_drv_pdata *)ptr; unsigned char *base = ep->base; u32 isr1, isr2, mask1, mask2; u32 ack; spin_lock(&ep->lock); isr1 = edp_read(base + 0x308); isr2 = edp_read(base + 0x30c); mask1 = isr1 & ep->mask1; mask2 = isr2 & ep->mask2; isr1 &= ~mask1; /* remove masks bit */ isr2 &= ~mask2; pr_debug("%s: isr=%x mask=%x isr2=%x mask2=%x\n", __func__, isr1, mask1, isr2, mask2); ack = isr1 & EDP_INTR_STATUS1; ack <<= 1; /* ack bits */ ack |= mask1; edp_write(base + 0x308, ack); ack = isr2 & EDP_INTR_STATUS2; ack <<= 1; /* ack bits */ ack |= mask2; edp_write(base + 0x30c, ack); spin_unlock(&ep->lock); if (isr1 & EDP_INTR_HPD) { isr1 &= ~EDP_INTR_HPD; /* clear */ edp_send_events(ep, EV_LINK_TRAIN); } if (isr2 & EDP_INTR_READY_FOR_VIDEO) edp_send_events(ep, EV_VIDEO_READY); if (isr2 & EDP_INTR_IDLE_PATTERNs_SENT) edp_send_events(ep, EV_IDLE_PATTERNS_SENT); if (isr1 && ep->aux_cmd_busy) { /* clear EDP_AUX_TRANS_CTRL */ edp_write(base + 0x318, 0); /* read EDP_INTERRUPT_TRANS_NUM */ ep->aux_trans_num = edp_read(base + 0x310); if (ep->aux_cmd_i2c) edp_aux_i2c_handler(ep, isr1); else edp_aux_native_handler(ep, isr1); } return IRQ_HANDLED; }
void mdss_edp_config_sync(unsigned char *edp_base) { int ret = 0; ret = edp_read(edp_base + 0xc); /* EDP_CONFIGURATION_CTRL */ ret &= ~0x733; ret |= (0x55 & 0x733); edp_write(edp_base + 0xc, ret); edp_write(edp_base + 0xc, 0x55); /* EDP_CONFIGURATION_CTRL */ }
static void edp_config_sync(void) { int ret = 0; ret = edp_read(EDP_BASE + 0xc); /* EDP_CONFIGURATION_CTRL */ ret &= ~0x733; ret |= (0x55 & 0x733); edp_write(EDP_BASE + 0xc, ret); edp_write(EDP_BASE + 0xc, 0x55); /* EDP_CONFIGURATION_CTRL */ }
static void mdss_edp_irq_disable(struct mdss_edp_drv_pdata *edp_drv) { unsigned long flags; spin_lock_irqsave(&edp_drv->lock, flags); edp_write(edp_drv->base + 0x308, 0x0); edp_write(edp_drv->base + 0x30c, 0x0); spin_unlock_irqrestore(&edp_drv->lock, flags); edp_drv->mdss_util->disable_irq(&mdss_edp_hw); }
void mdss_edp_phy_misc_cfg(unsigned char *edp_base) { /* EDP_PHY_EDPPHY_GLB_VM_CFG0 */ edp_write(edp_base + 0x510, 0x3); /* EDP_PHY_EDPPHY_GLB_VM_CFG1 */ edp_write(edp_base + 0x514, 0x64); /* EDP_PHY_EDPPHY_GLB_MISC9 */ edp_write(edp_base + 0x518, 0x6c); /* EDP_MISC1_MISC0 */ edp_write(edp_base + 0x2c, 0x1); }
static void mdss_edp_irq_enable(struct mdss_edp_drv_pdata *edp_drv) { unsigned long flags; spin_lock_irqsave(&edp_drv->lock, flags); edp_write(edp_drv->base + 0x308, edp_drv->mask1); edp_write(edp_drv->base + 0x30c, edp_drv->mask2); spin_unlock_irqrestore(&edp_drv->lock, flags); mdss_enable_irq(&mdss_edp_hw); }
void mdss_edp_enable_link_clk(unsigned char *mmss_cc_base, int enable) { if (!enable) { edp_write(mmss_cc_base + 0x0330, 0); /* CBCR */ return; } edp_write(mmss_cc_base + 0x00c4, (4 << 8)); /* CFG RCGR */ edp_write(mmss_cc_base + 0x00c0, 3); /* CMD RCGR */ edp_write(mmss_cc_base + 0x0330, 1); /* CBCR */ }
void mdss_edp_phy_powerup(unsigned char *edp_base, int enable) { if (enable) { /* EDP_PHY_EDPPHY_GLB_PD_CTL */ edp_write(edp_base + 0x52c, 0x3f); /* EDP_PHY_EDPPHY_GLB_CFG */ edp_write(edp_base + 0x528, 0x1); /* EDP_PHY_PLL_UNIPHY_PLL_GLB_CFG */ edp_write(edp_base + 0x620, 0xf); } else { /* EDP_PHY_EDPPHY_GLB_PD_CTL */ edp_write(edp_base + 0x52c, 0xc0); } }
void mdss_edp_phy_power_ctrl(struct mdss_edp_drv_pdata *ep, int enable) { if (enable) { /* EDP_PHY_EDPPHY_GLB_PD_CTL */ edp_write(ep->base + 0x52c, 0x3f); /* EDP_PHY_EDPPHY_GLB_CFG */ edp_write(ep->base + 0x528, 0x1); /* EDP_PHY_PLL_UNIPHY_PLL_GLB_CFG */ edp_write(ep->base + 0x620, 0xf); } else { /* EDP_PHY_EDPPHY_GLB_PD_CTL */ edp_write(ep->base + 0x52c, 0xc0); } }
static void edp_mainlink_ctrl(struct edp_ctrl *ctrl, int enable) { u32 data = 0; edp_write(ctrl->base + REG_EDP_MAINLINK_CTRL, EDP_MAINLINK_CTRL_RESET); /* Make sure fully reset */ wmb(); usleep_range(500, 1000); if (enable) data |= EDP_MAINLINK_CTRL_ENABLE; edp_write(ctrl->base + REG_EDP_MAINLINK_CTRL, data); }
static void edp_ctrl_irq_enable(struct edp_ctrl *ctrl, int enable) { unsigned long flags; DBG("%d", enable); spin_lock_irqsave(&ctrl->irq_lock, flags); if (enable) { edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_1, EDP_INTR_MASK1); edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_2, EDP_INTR_MASK2); } else { edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_1, 0x0); edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_2, 0x0); } spin_unlock_irqrestore(&ctrl->irq_lock, flags); DBG("exit"); }
void mdss_edp_enable_mainlink(unsigned char *edp_base, int enable) { u32 data; data = edp_read(edp_base + 0x004); data &= ~BIT(0); if (enable) { data |= 0x1; edp_write(edp_base + 0x004, data); edp_write(edp_base + 0x004, 0x1); } else { data |= 0x0; edp_write(edp_base + 0x004, data); } }
static void edp_clock_synchrous(struct edp_ctrl *ctrl, int sync) { u32 data; enum edp_color_depth depth; data = edp_read(ctrl->base + REG_EDP_MISC1_MISC0); if (sync) data |= EDP_MISC1_MISC0_SYNC; else data &= ~EDP_MISC1_MISC0_SYNC; /* only legacy rgb mode supported */ depth = EDP_6BIT; /* Default */ if (ctrl->color_depth == 8) depth = EDP_8BIT; else if (ctrl->color_depth == 10) depth = EDP_10BIT; else if (ctrl->color_depth == 12) depth = EDP_12BIT; else if (ctrl->color_depth == 16) depth = EDP_16BIT; data |= EDP_MISC1_MISC0_COLOR(depth); edp_write(ctrl->base + REG_EDP_MISC1_MISC0, data); }
void mdss_edp_config_ctrl(struct mdss_edp_drv_pdata *ep) { struct dpcd_cap *cap; struct display_timing_desc *dp; u32 data = 0; dp = &ep->edid.timing[0]; cap = &ep->dpcd; data = ep->lane_cnt - 1; data <<= 4; if (cap->enhanced_frame) data |= 0x40; if (ep->edid.color_depth == 8) { /* 0 == 6 bits, 1 == 8 bits */ data |= 0x100; /* bit 8 */ } if (!dp->interlaced) /* progressive */ data |= 0x04; data |= 0x03; /* sycn clock & static Mvid */ edp_write(ep->base + 0xc, data); /* EDP_CONFIGURATION_CTRL */ }
void mdss_edp_clock_synchrous(struct mdss_edp_drv_pdata *ep, int sync) { u32 data; u32 color; /* EDP_MISC1_MISC0 */ data = edp_read(ep->base + 0x02c); if (sync) data |= 0x01; else data &= ~0x01; /* only legacy rgb mode supported */ color = 0; /* 6 bits */ if (ep->edid.color_depth == 8) color = 0x01; else if (ep->edid.color_depth == 10) color = 0x02; else if (ep->edid.color_depth == 12) color = 0x03; else if (ep->edid.color_depth == 16) color = 0x04; color <<= 5; /* bit 5 to bit 7 */ data |= color; /* EDP_MISC1_MISC0 */ edp_write(ep->base + 0x2c, data); }
irqreturn_t msm_edp_ctrl_irq(struct edp_ctrl *ctrl) { u32 isr1, isr2, mask1, mask2; u32 ack; DBG(""); spin_lock(&ctrl->irq_lock); isr1 = edp_read(ctrl->base + REG_EDP_INTERRUPT_REG_1); isr2 = edp_read(ctrl->base + REG_EDP_INTERRUPT_REG_2); mask1 = isr1 & EDP_INTR_MASK1; mask2 = isr2 & EDP_INTR_MASK2; isr1 &= ~mask1; /* remove masks bit */ isr2 &= ~mask2; DBG("isr=%x mask=%x isr2=%x mask2=%x", isr1, mask1, isr2, mask2); ack = isr1 & EDP_INTR_STATUS1; ack <<= 1; /* ack bits */ ack |= mask1; edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_1, ack); ack = isr2 & EDP_INTR_STATUS2; ack <<= 1; /* ack bits */ ack |= mask2; edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_2, ack); spin_unlock(&ctrl->irq_lock); if (isr1 & EDP_INTERRUPT_REG_1_HPD) DBG("edp_hpd"); if (isr2 & EDP_INTERRUPT_REG_2_READY_FOR_VIDEO) DBG("edp_video_ready"); if (isr2 & EDP_INTERRUPT_REG_2_IDLE_PATTERNs_SENT) { DBG("idle_patterns_sent"); complete(&ctrl->idle_comp); } msm_edp_aux_irq(ctrl->aux, isr1); return IRQ_HANDLED; }
void mdss_edp_enable_lane_bist(unsigned char *edp_base, int lane, int enable) { unsigned char *addr_ln_bist_cfg, *addr_ln_pd_ctrl; /* EDP_PHY_EDPPHY_LNn_PD_CTL */ addr_ln_pd_ctrl = edp_base + 0x404 + (0x40 * lane); /* EDP_PHY_EDPPHY_LNn_BIST_CFG0 */ addr_ln_bist_cfg = edp_base + 0x408 + (0x40 * lane); if (enable) { edp_write(addr_ln_pd_ctrl, 0x0); edp_write(addr_ln_bist_cfg, 0x10); } else { edp_write(addr_ln_pd_ctrl, 0xf); edp_write(addr_ln_bist_cfg, 0x10); } }
/* EDP phy configuration settings */ void mdss_edp_phy_sw_reset(unsigned char *edp_base) { /* phy sw reset */ edp_write(edp_base + 0x74, 0x100); /* EDP_PHY_CTRL */ wmb(); usleep(1); edp_write(edp_base + 0x74, 0x000); /* EDP_PHY_CTRL */ wmb(); usleep(1); /* phy PLL sw reset */ edp_write(edp_base + 0x74, 0x001); /* EDP_PHY_CTRL */ wmb(); usleep(1); edp_write(edp_base + 0x74, 0x000); /* EDP_PHY_CTRL */ wmb(); usleep(1); }
void mdss_edp_hw_powerup(unsigned char *edp_base, int enable) { int ret = 0; if (enable) { /* EDP_PHY_EDPPHY_GLB_PD_CTL */ edp_write(edp_base + 0x52c, 0x3f); /* EDP_PHY_EDPPHY_GLB_CFG */ edp_write(edp_base + 0x528, 0x1); /* EDP_PHY_PLL_UNIPHY_PLL_GLB_CFG */ edp_write(edp_base + 0x620, 0xf); /* EDP_AUX_CTRL */ ret = edp_read(edp_base + 0x300); edp_write(edp_base + 0x300, ret | 0x1); } else { /* EDP_PHY_EDPPHY_GLB_PD_CTL */ edp_write(edp_base + 0x52c, 0xc0); } }
static int edp_sw_mvid_nvid(struct edp_ctrl *ctrl, u32 m, u32 n) { u32 n_multi, m_multi = 5; if (ctrl->link_rate == DP_LINK_BW_1_62) { n_multi = 1; } else if (ctrl->link_rate == DP_LINK_BW_2_7) { n_multi = 2; } else { pr_err("%s: Invalid link rate, %d\n", __func__, ctrl->link_rate); return -EINVAL; } edp_write(ctrl->base + REG_EDP_SOFTWARE_MVID, m * m_multi); edp_write(ctrl->base + REG_EDP_SOFTWARE_NVID, n * n_multi); return 0; }
static void mdss_edp_timing_cfg(struct mdss_edp_drv_pdata *ep) { struct mdss_panel_info *pinfo; u32 total_ver, total_hor; u32 data; pinfo = &ep->panel_data.panel_info; pr_debug("%s: width=%d hporch= %d %d %d\n", __func__, pinfo->xres, pinfo->lcdc.h_back_porch, pinfo->lcdc.h_front_porch, pinfo->lcdc.h_pulse_width); pr_debug("%s: height=%d vporch= %d %d %d\n", __func__, pinfo->yres, pinfo->lcdc.v_back_porch, pinfo->lcdc.v_front_porch, pinfo->lcdc.v_pulse_width); total_hor = pinfo->xres + pinfo->lcdc.h_back_porch + pinfo->lcdc.h_front_porch + pinfo->lcdc.h_pulse_width; total_ver = pinfo->yres + pinfo->lcdc.v_back_porch + pinfo->lcdc.v_front_porch + pinfo->lcdc.v_pulse_width; data = total_ver; data <<= 16; data |= total_hor; edp_write(ep->base + 0x1c, data); /* EDP_TOTAL_HOR_VER */ data = (pinfo->lcdc.v_back_porch + pinfo->lcdc.v_pulse_width); data <<= 16; data |= (pinfo->lcdc.h_back_porch + pinfo->lcdc.h_pulse_width); edp_write(ep->base + 0x20, data); /* EDP_START_HOR_VER_FROM_SYNC */ data = pinfo->lcdc.v_pulse_width; data <<= 16; data |= pinfo->lcdc.h_pulse_width; edp_write(ep->base + 0x24, data); /* EDP_HSYNC_VSYNC_WIDTH_POLARITY */ data = pinfo->yres; data <<= 16; data |= pinfo->xres; edp_write(ep->base + 0x28, data); /* EDP_ACTIVE_HOR_VER */ }
void mdss_edp_aux_ctrl(struct mdss_edp_drv_pdata *ep, int enable) { u32 data; data = edp_read(ep->base + 0x300); if (enable) data |= 0x01; else data |= ~0x01; edp_write(ep->base + 0x300, data); /* EDP_AUX_CTRL */ }
void mdss_edp_aux_ctrl(unsigned char *edp_base, int enable) { u32 data; data = edp_read(edp_base + 0x300); if (enable) data |= 0x01; else data |= ~0x01; edp_write(edp_base + 0x300, data); /* EDP_AUX_CTRL */ }
void mdss_edp_mainlink_ctrl(struct mdss_edp_drv_pdata *ep, int enable) { u32 data; data = edp_read(ep->base + 0x04); data &= ~BIT(0); if (enable) data |= 0x1; edp_write(ep->base + 0x04, data); }
static int edp_cmd_fifo_tx(struct edp_buf *tp, unsigned char *base) { u32 data; char *dp; int len, cnt; u32 reg; len = tp->len; /* total byte to cmd fifo */ if (len == 0) return 0; cnt = 0; dp = tp->start; while (cnt < len) { data = *dp; /* data byte */ data <<= 8; data &= 0x00ff00; /* index = 0, write */ if (cnt == 0) data |= BIT(31); /* INDEX_WRITE */ pr_debug("%s: data=%x\n", __func__, data); edp_write(base + EDP_AUX_DATA, data); cnt++; dp++; } data = (tp->trans_num - 1); if (tp->i2c) data |= BIT(8); /* I2C */ /* To clear BIT(9) GO bit */ reg = edp_read(base + EDP_AUX_TRANS_CTRL); edp_write(base + EDP_AUX_TRANS_CTRL, reg & (~(0x1 << 9))); data |= BIT(9); /* GO */ pr_debug("%s: data=%x\n", __func__, data); edp_write(base + EDP_AUX_TRANS_CTRL, data); return tp->len; }
static void edp_config_timing(struct msm_panel_info *pinfo) { unsigned long total_ver, total_hor; unsigned long data; dprintf(INFO, "%s: width=%d hporch= %d %d %d\n", __func__, pinfo->xres, pinfo->lcdc.h_back_porch, pinfo->lcdc.h_front_porch, pinfo->lcdc.h_pulse_width); dprintf(INFO, "%s: height=%d vporch= %d %d %d\n", __func__, pinfo->yres, pinfo->lcdc.v_back_porch, pinfo->lcdc.v_front_porch, pinfo->lcdc.v_pulse_width); total_hor = pinfo->xres + pinfo->lcdc.h_back_porch + pinfo->lcdc.h_front_porch + pinfo->lcdc.h_pulse_width; total_ver = pinfo->yres + pinfo->lcdc.v_back_porch + pinfo->lcdc.v_front_porch + pinfo->lcdc.v_pulse_width; data = total_ver; data <<= 16; data |= total_hor; edp_write(EDP_BASE + 0x1c, data); /* EDP_TOTAL_HOR_VER */ data = (pinfo->lcdc.v_back_porch + pinfo->lcdc.v_pulse_width); data <<= 16; data |= (pinfo->lcdc.h_back_porch + pinfo->lcdc.h_pulse_width); edp_write(EDP_BASE + 0x20, data); /* EDP_START_HOR_VER_FROM_SYNC */ data = pinfo->lcdc.v_pulse_width; data <<= 16; data |= pinfo->lcdc.h_pulse_width; edp_write(EDP_BASE + 0x24, data); /* EDP_HSYNC_VSYNC_WIDTH_POLARITY */ data = pinfo->yres; data <<= 16; data |= pinfo->xres; edp_write(EDP_BASE + 0x28, data); /* EDP_ACTIVE_HOR_VER */ }
void mdss_edp_clock_synchrous(unsigned char *edp_base, int sync) { u32 data; /* EDP_MISC1_MISC0 */ data = edp_read(edp_base + 0x02c); if (sync) data |= 0x01; else data &= ~0x01; /* EDP_MISC1_MISC0 */ edp_write(edp_base + 0x2c, data); }
void mdss_edp_lane_power_ctrl(unsigned char *edp_base, int max_lane, int up) { int i, off; u32 data; if (up) data = 0; /* power up */ else data = 0x7; /* power down */ /* EDP_PHY_EDPPHY_LNn_PD_CTL */ for (i = 0; i < max_lane; i++) { off = 0x40 * i; edp_write(edp_base + 0x404 + off , data); } }