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_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); }
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); }
static void edp_config_static_mdiv(void) { int ret = 0; ret = edp_read(EDP_BASE + 0xc); /* EDP_CONFIGURATION_CTRL */ edp_write(EDP_BASE + 0xc, ret | 0x2); /* EDP_CONFIGURATION_CTRL */ edp_write(EDP_BASE + 0xc, 0x57); /* EDP_CONFIGURATION_CTRL */ }
static void mdss_edp_config_static_mdiv(unsigned char *edp_base) { int ret = 0; ret = edp_read(edp_base + 0xc); /* EDP_CONFIGURATION_CTRL */ edp_write(edp_base + 0xc, ret | 0x2); /* EDP_CONFIGURATION_CTRL */ edp_write(edp_base + 0xc, 0x57); /* EDP_CONFIGURATION_CTRL */ }
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; }
int mdss_edp_phy_ready(unsigned char *edp_base) { u32 status; status = edp_read(edp_base + 0x598); status &= 0x01; return status; }
int mdss_edp_phy_ready(struct mdss_edp_drv_pdata *ep) { u32 status; status = edp_read(ep->base + 0x598); status &= 0x01; return status; }
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 */ }
int mdss_edp_off(struct mdss_panel_data *pdata) { struct mdss_edp_drv_pdata *edp_drv = NULL; int ret = 0; edp_drv = container_of(pdata, struct mdss_edp_drv_pdata, panel_data); if (!edp_drv) { pr_err("%s: Invalid input data\n", __func__); return -EINVAL; } pr_debug("%s:+, cont_splash=%d\n", __func__, edp_drv->cont_splash); /* wait until link training is completed */ mutex_lock(&edp_drv->train_mutex); INIT_COMPLETION(edp_drv->idle_comp); mdss_edp_state_ctrl(edp_drv, ST_PUSH_IDLE); ret = wait_for_completion_timeout(&edp_drv->idle_comp, msecs_to_jiffies(100)); if (ret == 0) pr_err("%s: idle pattern timedout\n", __func__); mdss_edp_state_ctrl(edp_drv, 0); mdss_edp_sink_power_state(edp_drv, SINK_POWER_OFF); mdss_edp_irq_disable(edp_drv); gpio_set_value(edp_drv->gpio_panel_en, 0); if (gpio_is_valid(edp_drv->gpio_lvl_en)) gpio_set_value(edp_drv->gpio_lvl_en, 0); if (edp_drv->bl_pwm != NULL) pwm_disable(edp_drv->bl_pwm); edp_drv->is_pwm_enabled = 0; mdss_edp_mainlink_reset(edp_drv); mdss_edp_mainlink_ctrl(edp_drv, 0); mdss_edp_lane_power_ctrl(edp_drv, 0); mdss_edp_phy_power_ctrl(edp_drv, 0); mdss_edp_clk_disable(edp_drv); mdss_edp_unprepare_clocks(edp_drv); mdss_edp_aux_ctrl(edp_drv, 0); pr_debug("%s-: state_ctrl=%x\n", __func__, edp_read(edp_drv->base + 0x8)); mutex_unlock(&edp_drv->train_mutex); return 0; }
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_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_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_rx(struct edp_buf *rp, int len, unsigned char *base) { u32 data; char *dp; int i; data = 0; /* index = 0 */ data |= BIT(31); /* INDEX_WRITE */ data |= BIT(0); /* read */ edp_write(base + EDP_AUX_DATA, data); dp = rp->data; /* discard first byte */ data = edp_read(base + EDP_AUX_DATA); for (i = 0; i < len; i++) { data = edp_read(base + EDP_AUX_DATA); pr_debug("%s: data=%x\n", __func__, data); *dp++ = (char)((data >> 8) & 0xff); } rp->len = len; return len; }
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_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); } }
int mdss_edp_mainlink_ready(struct mdss_edp_drv_pdata *ep, u32 which) { u32 data; int cnt = 10; while (--cnt) { data = edp_read(ep->base + 0x84); /* EDP_MAINLINK_READY */ if (data & which) { pr_debug("%s: which=%x ready\n", __func__, which); return 1; } usleep(1000); } pr_err("%s: which=%x NOT ready\n", __func__, which); return 0; }
static void edp_host_train_set(struct edp_ctrl *ctrl, u32 train) { int cnt = 10; u32 data; u32 shift = train - 1; DBG("train=%d", train); edp_state_ctrl(ctrl, EDP_STATE_CTRL_TRAIN_PATTERN_1 << shift); while (--cnt) { data = edp_read(ctrl->base + REG_EDP_MAINLINK_READY); if (data & (EDP_MAINLINK_READY_TRAIN_PATTERN_1_READY << shift)) break; } if (cnt == 0) pr_err("%s: set link_train=%d failed\n", __func__, train); }
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); } }
int mdss_edp_phy_pll_ready(unsigned char *edp_base) { int cnt; u32 status; cnt = 10; while (cnt--) { status = edp_read(edp_base + 0x6c0); if (status & 0x01) break; usleep(100); } if (cnt == 0) { pr_err("%s: PLL NOT ready\n", __func__); return 0; } else return 1; }
int mdss_edp_phy_pll_ready(struct mdss_edp_drv_pdata *ep) { int cnt; u32 status = 0; cnt = 100; while (--cnt) { status = edp_read(ep->base + 0x6c0); if (status & 0x01) break; usleep(100); } pr_debug("%s: PLL cnt=%d status=%x\n", __func__, cnt, (int)status); if (cnt <= 0) { pr_err("%s: PLL NOT ready\n", __func__); return 0; } else return 1; }
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; }
void mdss_edp_clk_debug(unsigned char *edp_base, unsigned char *mmss_cc_base) { u32 da4, da0, d32c; u32 dc4, dc0, d330; /* pixel clk */ da0 = edp_read(mmss_cc_base + 0x0a0); da4 = edp_read(mmss_cc_base + 0x0a4); d32c = edp_read(mmss_cc_base + 0x32c); /* main link clk */ dc0 = edp_read(mmss_cc_base + 0x0c0); dc4 = edp_read(mmss_cc_base + 0x0c4); d330 = edp_read(mmss_cc_base + 0x330); pr_err("%s: da0=%x da4=%x d32c=%x dc0=%x dc4=%x d330=%x\n", __func__, (int)da0, (int)da4, (int)d32c, (int)dc0, (int)dc4, (int)d330); }