static void hdmi_phy_8960_reset(struct hdmi_phy *phy) { struct hdmi_phy_8960 *phy_8960 = to_hdmi_phy_8960(phy); struct hdmi *hdmi = phy_8960->hdmi; unsigned int val; val = hdmi_read(hdmi, REG_HDMI_PHY_CTRL); if (val & HDMI_PHY_CTRL_SW_RESET_LOW) { /* pull low */ hdmi_write(hdmi, REG_HDMI_PHY_CTRL, val & ~HDMI_PHY_CTRL_SW_RESET); } else { /* pull high */ hdmi_write(hdmi, REG_HDMI_PHY_CTRL, val | HDMI_PHY_CTRL_SW_RESET); } if (val & HDMI_PHY_CTRL_SW_RESET_PLL_LOW) { /* pull low */ hdmi_write(hdmi, REG_HDMI_PHY_CTRL, val & ~HDMI_PHY_CTRL_SW_RESET_PLL); } else { /* pull high */ hdmi_write(hdmi, REG_HDMI_PHY_CTRL, val | HDMI_PHY_CTRL_SW_RESET_PLL); } msleep(100); if (val & HDMI_PHY_CTRL_SW_RESET_LOW) { /* pull high */ hdmi_write(hdmi, REG_HDMI_PHY_CTRL, val | HDMI_PHY_CTRL_SW_RESET); } else { /* pull low */ hdmi_write(hdmi, REG_HDMI_PHY_CTRL, val & ~HDMI_PHY_CTRL_SW_RESET); } if (val & HDMI_PHY_CTRL_SW_RESET_PLL_LOW) { /* pull high */ hdmi_write(hdmi, REG_HDMI_PHY_CTRL, val | HDMI_PHY_CTRL_SW_RESET_PLL); } else { /* pull low */ hdmi_write(hdmi, REG_HDMI_PHY_CTRL, val & ~HDMI_PHY_CTRL_SW_RESET_PLL); } }
static enum drm_connector_status detect_reg(struct hdmi *hdmi) { uint32_t hpd_int_status; pm_runtime_get_sync(&hdmi->pdev->dev); enable_hpd_clocks(hdmi, true); hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS); enable_hpd_clocks(hdmi, false); pm_runtime_put_autosuspend(&hdmi->pdev->dev); return (hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED) ? connector_status_connected : connector_status_disconnected; }
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 void sh_hdmi_read_edid(struct sh_hdmi *hdmi) { struct fb_var_screeninfo *var = &hdmi->var; struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; struct fb_videomode *lcd_cfg = &pdata->lcd_chan->lcd_cfg; unsigned long height = var->height, width = var->width; int i; u8 edid[128]; /* Read EDID */ pr_debug("Read back EDID code:"); for (i = 0; i < 128; i++) { edid[i] = hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW); #ifdef DEBUG if ((i % 16) == 0) { printk(KERN_CONT "\n"); printk(KERN_DEBUG "%02X | %02X", i, edid[i]); } else { printk(KERN_CONT " %02X", edid[i]); } #endif } #ifdef DEBUG printk(KERN_CONT "\n"); #endif fb_parse_edid(edid, var); pr_debug("%u-%u-%u-%u x %u-%u-%u-%u @ %lu kHz monitor detected\n", var->left_margin, var->xres, var->right_margin, var->hsync_len, var->upper_margin, var->yres, var->lower_margin, var->vsync_len, PICOS2KHZ(var->pixclock)); var->width = width; var->xres = lcd_cfg->xres; var->xres_virtual = lcd_cfg->xres; var->left_margin = lcd_cfg->left_margin; var->right_margin = lcd_cfg->right_margin; var->hsync_len = lcd_cfg->hsync_len; var->height = height; var->yres = lcd_cfg->yres; var->yres_virtual = lcd_cfg->yres * 2; var->upper_margin = lcd_cfg->upper_margin; var->lower_margin = lcd_cfg->lower_margin; var->vsync_len = lcd_cfg->vsync_len; var->sync = lcd_cfg->sync; var->pixclock = lcd_cfg->pixclock; hdmi_external_video_param(hdmi); }
static void msm_hdmi_phy_reset(struct hdmi *hdmi) { unsigned int val; val = hdmi_read(hdmi, REG_HDMI_PHY_CTRL); if (val & HDMI_PHY_CTRL_SW_RESET_LOW) { /* pull low */ hdmi_write(hdmi, REG_HDMI_PHY_CTRL, val & ~HDMI_PHY_CTRL_SW_RESET); } else { /* pull high */ hdmi_write(hdmi, REG_HDMI_PHY_CTRL, val | HDMI_PHY_CTRL_SW_RESET); } if (val & HDMI_PHY_CTRL_SW_RESET_PLL_LOW) { /* pull low */ hdmi_write(hdmi, REG_HDMI_PHY_CTRL, val & ~HDMI_PHY_CTRL_SW_RESET_PLL); } else { /* pull high */ hdmi_write(hdmi, REG_HDMI_PHY_CTRL, val | HDMI_PHY_CTRL_SW_RESET_PLL); } msleep(100); if (val & HDMI_PHY_CTRL_SW_RESET_LOW) { /* pull high */ hdmi_write(hdmi, REG_HDMI_PHY_CTRL, val | HDMI_PHY_CTRL_SW_RESET); } else { /* pull low */ hdmi_write(hdmi, REG_HDMI_PHY_CTRL, val & ~HDMI_PHY_CTRL_SW_RESET); } if (val & HDMI_PHY_CTRL_SW_RESET_PLL_LOW) { /* pull high */ hdmi_write(hdmi, REG_HDMI_PHY_CTRL, val | HDMI_PHY_CTRL_SW_RESET_PLL); } else { /* pull low */ hdmi_write(hdmi, REG_HDMI_PHY_CTRL, val & ~HDMI_PHY_CTRL_SW_RESET_PLL); } }
irqreturn_t hdmi_irq_handler(int irq, void *dev_data) { struct hdmi_device *hdev = dev_data; u32 intc_flag; (void)irq; intc_flag = hdmi_read(hdev, HDMI_INTC_FLAG); /* clearing flags for HPD plug/unplug */ if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) { printk(KERN_INFO "unplugged\n"); hdmi_write_mask(hdev, HDMI_INTC_FLAG, ~0, HDMI_INTC_FLAG_HPD_UNPLUG); } if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) { printk(KERN_INFO "plugged\n"); hdmi_write_mask(hdev, HDMI_INTC_FLAG, ~0, HDMI_INTC_FLAG_HPD_PLUG); } return IRQ_HANDLED; }
unsigned int bsp_hdmi_get_hpd() { unsigned int ret = 0; hdmi_write(0x10010,0x45); hdmi_write(0x10011,0x45); hdmi_write(0x10012,0x52); hdmi_write(0x10013,0x54); if( (hdmi_read(0x0243) & 0x2) == 0x2) ret = 1; else ret = 0; hdmi_write(0x10010,0x52); hdmi_write(0x10011,0x54); hdmi_write(0x10012,0x41); hdmi_write(0x10013,0x57); return ret; }
/** * Stop hdmi phy macro cell tx3g4c28 * * @hdmi: pointer on the hdmi internal structure */ static void sti_hdmi_tx3g4c28phy_stop(struct sti_hdmi *hdmi) { int val = 0; DRM_DEBUG_DRIVER("\n"); hdmi->event_received = false; val = HDMI_SRZ_CFG_EN_SINK_TERM_DETECTION; val |= HDMI_SRZ_CFG_EN_BIASRES_DETECTION; hdmi_write(hdmi, val, HDMI_SRZ_CFG); hdmi_write(hdmi, 0, HDMI_SRZ_PLL_CFG); /* wait PLL interrupt */ wait_event_interruptible_timeout(hdmi->wait_event, hdmi->event_received == true, msecs_to_jiffies (HDMI_TIMEOUT_PLL_LOCK)); if (hdmi_read(hdmi, HDMI_STA) & HDMI_STA_DLL_LCK) DRM_ERROR("hdmi phy pll not well disabled\n"); }
static int hdmi_clear(uint8_t page, uint8_t reg, uint8_t mask) { int r; uint8_t val; val = 0x00; r = hdmi_read(page, reg, &val); if (r != OK) { return r; } val &= ~mask; r = hdmi_write(page, reg, val); if (r != OK) { return r; } return OK; }
static int hdmi_connector_get_modes(struct drm_connector *connector) { struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector); struct hdmi *hdmi = hdmi_connector->hdmi; struct edid *edid; uint32_t hdmi_ctrl; int ret = 0; hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL); hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE); edid = drm_get_edid(connector, hdmi->i2c); hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl); drm_mode_connector_update_edid_property(connector, edid); if (edid) { ret = drm_add_edid_modes(connector, edid); kfree(edid); } return ret; }
/** * Start hdmi phy macro cell tx3g4c28 * * @hdmi: pointer on the hdmi internal structure * * Return false if an error occur */ static bool sti_hdmi_tx3g4c28phy_start(struct sti_hdmi *hdmi) { u32 ckpxpll = hdmi->mode.clock * 1000; u32 val, tmdsck, idf, odf, pllctrl = 0; bool foundplldivides = false; int i; DRM_DEBUG_DRIVER("ckpxpll = %dHz\n", ckpxpll); for (i = 0; i < NB_PLL_MODE; i++) { if (ckpxpll >= plldividers[i].min && ckpxpll < plldividers[i].max) { idf = plldividers[i].idf; odf = plldividers[i].odf; foundplldivides = true; break; } } if (!foundplldivides) { DRM_ERROR("input TMDS clock speed (%d) not supported\n", ckpxpll); goto err; } /* Assuming no pixel repetition and 24bits color */ tmdsck = ckpxpll; pllctrl |= 40 << PLL_CFG_NDIV_SHIFT; if (tmdsck > 340000000) { DRM_ERROR("output TMDS clock (%d) out of range\n", tmdsck); goto err; } pllctrl |= idf << PLL_CFG_IDF_SHIFT; pllctrl |= odf << PLL_CFG_ODF_SHIFT; /* * Configure and power up the PHY PLL */ hdmi->event_received = false; DRM_DEBUG_DRIVER("pllctrl = 0x%x\n", pllctrl); hdmi_write(hdmi, (pllctrl | PLL_CFG_EN), HDMI_SRZ_PLL_CFG); /* wait PLL interrupt */ wait_event_interruptible_timeout(hdmi->wait_event, hdmi->event_received == true, msecs_to_jiffies (HDMI_TIMEOUT_PLL_LOCK)); if ((hdmi_read(hdmi, HDMI_STA) & HDMI_STA_DLL_LCK) == 0) { DRM_ERROR("hdmi phy pll not locked\n"); goto err; } DRM_DEBUG_DRIVER("got PHY PLL Lock\n"); val = (HDMI_SRZ_CFG_EN | HDMI_SRZ_CFG_EXTERNAL_DATA | HDMI_SRZ_CFG_EN_BIASRES_DETECTION | HDMI_SRZ_CFG_EN_SINK_TERM_DETECTION); if (tmdsck > 165000000) val |= HDMI_SRZ_CFG_EN_SRC_TERMINATION; /* * To configure the source termination and pre-emphasis appropriately * for different high speed TMDS clock frequencies a phy configuration * table must be provided, tailored to the SoC and board combination. */ for (i = 0; i < NB_HDMI_PHY_CONFIG; i++) { if ((hdmiphy_config[i].min_tmds_freq <= tmdsck) && (hdmiphy_config[i].max_tmds_freq >= tmdsck)) { val |= (hdmiphy_config[i].config[0] & ~HDMI_SRZ_CFG_INTERNAL_MASK); hdmi_write(hdmi, val, HDMI_SRZ_CFG); val = hdmiphy_config[i].config[1]; hdmi_write(hdmi, val, HDMI_SRZ_ICNTL); val = hdmiphy_config[i].config[2]; hdmi_write(hdmi, val, HDMI_SRZ_CALCODE_EXT); DRM_DEBUG_DRIVER("serializer cfg 0x%x 0x%x 0x%x\n", hdmiphy_config[i].config[0], hdmiphy_config[i].config[1], hdmiphy_config[i].config[2]); return true; } } /* * Default, power up the serializer with no pre-emphasis or * output swing correction */ hdmi_write(hdmi, val, HDMI_SRZ_CFG); hdmi_write(hdmi, 0x0, HDMI_SRZ_ICNTL); hdmi_write(hdmi, 0x0, HDMI_SRZ_CALCODE_EXT); return true; err: return false; }
static int hpd_enable(struct hdmi_connector *hdmi_connector) { struct hdmi *hdmi = hdmi_connector->hdmi; const struct hdmi_platform_config *config = hdmi->config; struct drm_device *dev = hdmi_connector->base.dev; struct hdmi_phy *phy = hdmi->phy; uint32_t hpd_ctrl; int i, ret; ret = gpio_config(hdmi, true); if (ret) { dev_err(dev->dev, "failed to configure GPIOs: %d\n", ret); goto fail; } for (i = 0; i < config->hpd_clk_cnt; i++) { if (config->hpd_freq && config->hpd_freq[i]) { ret = clk_set_rate(hdmi->hpd_clks[i], config->hpd_freq[i]); if (ret) dev_warn(dev->dev, "failed to set clk %s (%d)\n", config->hpd_clk_names[i], ret); } ret = clk_prepare_enable(hdmi->hpd_clks[i]); if (ret) { dev_err(dev->dev, "failed to enable hpd clk: %s (%d)\n", config->hpd_clk_names[i], ret); goto fail; } } for (i = 0; i < config->hpd_reg_cnt; i++) { ret = regulator_enable(hdmi->hpd_regs[i]); if (ret) { dev_err(dev->dev, "failed to enable hpd regulator: %s (%d)\n", config->hpd_reg_names[i], ret); goto fail; } } hdmi_set_mode(hdmi, false); phy->funcs->reset(phy); hdmi_set_mode(hdmi, true); hdmi_write(hdmi, REG_HDMI_USEC_REFTIMER, 0x0001001b); /* enable HPD events: */ hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, HDMI_HPD_INT_CTRL_INT_CONNECT | HDMI_HPD_INT_CTRL_INT_EN); /* set timeout to 4.1ms (max) for hardware debounce */ hpd_ctrl = hdmi_read(hdmi, REG_HDMI_HPD_CTRL); hpd_ctrl |= HDMI_HPD_CTRL_TIMEOUT(0x1fff); /* Toggle HPD circuit to trigger HPD sense */ hdmi_write(hdmi, REG_HDMI_HPD_CTRL, ~HDMI_HPD_CTRL_ENABLE & hpd_ctrl); hdmi_write(hdmi, REG_HDMI_HPD_CTRL, HDMI_HPD_CTRL_ENABLE | hpd_ctrl); return 0; fail: return ret; }
static int hdmi_streamon(struct hdmi_device *hdev) { struct device *dev = hdev->dev; int ret; u32 val0, val1, val2; dev_dbg(dev, "%s\n", __func__); /* 3D test */ hdmi_set_infoframe(hdev); /* set packets for audio */ hdmi_set_packets(hdev); /* init audio */ #if defined(CONFIG_VIDEO_EXYNOS_HDMI_AUDIO_I2S) //printk("=============================> HDMI IIS\n"); hdmi_reg_i2s_audio_init(hdev); #elif defined(CONFIG_VIDEO_EXYNOS_HDMI_AUDIO_SPDIF) hdmi_reg_spdif_audio_init(hdev); #endif /* enbale HDMI audio */ if (hdev->audio_enable) { //printk("<+++++++++++++++++++++++++++++++++++++++++++ HDMI ENABLE\n"); hdmi_audio_enable(hdev, 1); //printk("<+++++++++++++++++++++++++++++++++++++++++++ HDMI ENABLE\n"); } hdmi_set_dvi_mode(hdev); /* controls the pixel value limitation */ hdmi_reg_set_limits(hdev); /* enable HDMI and timing generator */ hdmi_enable(hdev, 1); hdmi_tg_enable(hdev, 1); hdmi_reg_set_int_hpd(hdev); hdev->streaming = HDMI_STREAMING; // if (edid_supports_hdmi(hdev)) { #if 1 /* start HDCP if enabled */ if (hdev->hdcp_info.hdcp_enable) { ret = hdcp_start(hdev); if (ret) return ret; } #endif // } val0 = hdmi_read(hdev, HDMI_ACR_MCTS0); val1 = hdmi_read(hdev, HDMI_ACR_MCTS1); val2 = hdmi_read(hdev, HDMI_ACR_MCTS2); dev_dbg(dev, "HDMI_ACR_MCTS0 : 0x%08x\n", val0); dev_dbg(dev, "HDMI_ACR_MCTS1 : 0x%08x\n", val1); dev_dbg(dev, "HDMI_ACR_MCTS2 : 0x%08x\n", val2); hdmi_dumpregs(hdev, "streamon"); return 0; }
static int sh_hdmi_read_edid(struct sh_hdmi *hdmi) { struct fb_var_screeninfo tmpvar; struct fb_var_screeninfo *var = &tmpvar; const struct fb_videomode *mode, *found = NULL; struct fb_info *info = hdmi->info; struct fb_modelist *modelist = NULL; unsigned int f_width = 0, f_height = 0, f_refresh = 0; unsigned long found_rate_error = ULONG_MAX; /* silly compiler... */ bool exact_match = false; u8 edid[128]; char *forced; int i; /* Read EDID */ dev_dbg(hdmi->dev, "Read back EDID code:"); for (i = 0; i < 128; i++) { edid[i] = hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW); #ifdef DEBUG if ((i % 16) == 0) { printk(KERN_CONT "\n"); printk(KERN_DEBUG "%02X | %02X", i, edid[i]); } else { printk(KERN_CONT " %02X", edid[i]); } #endif } #ifdef DEBUG printk(KERN_CONT "\n"); #endif fb_edid_to_monspecs(edid, &hdmi->monspec); fb_get_options("sh_mobile_lcdc", &forced); if (forced && *forced) { /* Only primitive parsing so far */ i = sscanf(forced, "%ux%u@%u", &f_width, &f_height, &f_refresh); if (i < 2) { f_width = 0; f_height = 0; } dev_dbg(hdmi->dev, "Forced mode %ux%u@%uHz\n", f_width, f_height, f_refresh); } /* Walk monitor modes to find the best or the exact match */ for (i = 0, mode = hdmi->monspec.modedb; f_width && f_height && i < hdmi->monspec.modedb_len && !exact_match; i++, mode++) { unsigned long rate_error = sh_hdmi_rate_error(hdmi, mode); /* No interest in unmatching modes */ if (f_width != mode->xres || f_height != mode->yres) continue; if (f_refresh == mode->refresh || (!f_refresh && !rate_error)) /* * Exact match if either the refresh rate matches or it * hasn't been specified and we've found a mode, for * which we can configure the clock precisely */ exact_match = true; else if (found && found_rate_error <= rate_error) /* * We otherwise search for the closest matching clock * rate - either if no refresh rate has been specified * or we cannot find an exactly matching one */ continue; /* Check if supported: sufficient fb memory, supported clock-rate */ fb_videomode_to_var(var, mode); if (info && info->fbops->fb_check_var && info->fbops->fb_check_var(var, info)) { exact_match = false; continue; } found = mode; found_rate_error = rate_error; } /* * TODO 1: if no ->info is present, postpone running the config until * after ->info first gets registered. * TODO 2: consider registering the HDMI platform device from the LCDC * driver, and passing ->info with HDMI platform data. */ if (info && !found) { modelist = hdmi->info->modelist.next && !list_empty(&hdmi->info->modelist) ? list_entry(hdmi->info->modelist.next, struct fb_modelist, list) : NULL; if (modelist) { found = &modelist->mode; found_rate_error = sh_hdmi_rate_error(hdmi, found); } }
int bsp_hdmi_video(struct video_para *video) { unsigned id = get_vid(video->vic); glb_video.vic = video->vic; bsp_hdmi_init(); hdmi_write(0x0840, 0x01); hdmi_write(0x4845, 0x00); hdmi_write(0x0040, ptbl[id].para[3] | 0x10); hdmi_write(0x10001, ( (ptbl[id].para[3] < 96) ? 0x03 : 0x00 ) ); hdmi_write(0x8040, ptbl[id].para[4]); hdmi_write(0x4043, ptbl[id].para[5]); hdmi_write(0x8042, ptbl[id].para[6]); hdmi_write(0x0042, ptbl[id].para[7]); hdmi_write(0x4042, ptbl[id].para[8]); hdmi_write(0x4041, ptbl[id].para[9]); hdmi_write(0xC041, ptbl[id].para[10]); hdmi_write(0x0041, ptbl[id].para[11]); hdmi_write(0x8041, ptbl[id].para[12]); hdmi_write(0x4040, ptbl[id].para[13]); hdmi_write(0xC040, ptbl[id].para[14]); hdmi_write(0x0043, ptbl[id].para[15]); hdmi_write(0x8043, ptbl[id].para[16]); hdmi_write(0x0045, 0x0c); hdmi_write(0x8044, 0x20); hdmi_write(0x8045, 0x01); hdmi_write(0x0046, 0x0b); hdmi_write(0x0047, 0x16); hdmi_write(0x8046, 0x21); hdmi_write(0x3048, ptbl[id].para[2] ? 0x21 : 0x10); hdmi_write(0x0401, ptbl[id].para[2] ? 0x41 : 0x40); hdmi_write(0x8400, 0x07); hdmi_write(0x8401, 0x00); hdmi_write(0x0402, 0x47); hdmi_write(0x0800, video->is_yuv ? 0x09 : 0x01); hdmi_write(0x0801, 0x07); hdmi_write(0x8800, 0x00); hdmi_write(0x8801, 0x00); hdmi_write(0x0802, 0x00); hdmi_write(0x0803, 0x00); hdmi_write(0x8802, 0x00); hdmi_write(0x8803, 0x00); if(video->is_hdmi) { hdmi_write(0xB045, 0x08); hdmi_write(0x2045, 0x00); hdmi_write(0x2044, 0x0c); hdmi_write(0x6041, 0x03); hdmi_write(0xA044, ((ptbl[id].para[0]&0x100) == 0x100) ? 0x20 : ( ((ptbl[id].para[0]&0x80) == 0x80) ? 0x40 : 0x00) ); hdmi_write(0xA045, ((ptbl[id].para[0]&0x100) == 0x100) ? (ptbl[id].para[0]&0x7f) : 0x00); hdmi_write(0x2046, 0x00); hdmi_write(0x3046, 0x01); hdmi_write(0x3047, 0x11); hdmi_write(0x4044, 0x00); hdmi_write(0x0052, 0x00); hdmi_write(0x8051, 0x11); hdmi_write(0x10010,0x45); hdmi_write(0x10011,0x45); hdmi_write(0x10012,0x52); hdmi_write(0x10013,0x54); hdmi_write(0x0040, hdmi_read(0x0040) | 0x08 ); hdmi_write(0x10010,0x52); hdmi_write(0x10011,0x54); hdmi_write(0x10012,0x41); hdmi_write(0x10013,0x57); hdmi_write(0x4045, video->is_yuv ? 0x02 : 0x00); if(ptbl[id].para[16] == 0) hdmi_write(0xC044, (video->csc << 6) | 0x18); else if(ptbl[id].para[16] == 1) hdmi_write(0xC044, (video->csc << 6) | 0x28); else hdmi_write(0xC044, (video->csc << 6) | 0x08); hdmi_write(0xC045, 0x00); hdmi_write(0x4046, ptbl[id].para[0]&0x7f); } if(video->is_hcts) { hdmi_write(0x10010,0x45); hdmi_write(0x10011,0x45); hdmi_write(0x10012,0x52); hdmi_write(0x10013,0x54); hdmi_write(0x0040, hdmi_read(0x0040) | 0x80 ); hdmi_write(0x10010,0x52); hdmi_write(0x10011,0x54); hdmi_write(0x10012,0x41); hdmi_write(0x10013,0x57); } hdmi_write(0x0082, 0x00); hdmi_write(0x0081, 0x00); if(hdmi_phy_set(video)!=0) return -1; hdmi_write(0x0840, 0x00); if(video->is_hcts) { } return 0; }
static int hdmi_streamon(struct hdmi_device *hdev) { const struct hdmi_timings *conf = hdev->cur_conf; struct device *dev = hdev->dev; int ret; u32 val0, val1, val2; dev_dbg(dev, "%s\n", __func__); /* 3D test */ hdmi_set_infoframe(hdev); /* set packets for audio */ hdmi_set_packets(hdev); /* init audio */ #if defined(CONFIG_VIDEO_EXYNOS_HDMI_AUDIO_I2S) hdmi_reg_i2s_audio_init(hdev); #elif defined(CONFIG_VIDEO_EXYNOS_HDMI_AUDIO_SPDIF) hdmi_reg_spdif_audio_init(hdev); #endif /* enbale HDMI audio */ if (hdev->audio_enable) hdmi_audio_enable(hdev, 1); hdmi_set_dvi_mode(hdev); /* controls the pixel value limitation */ hdmi_reg_set_limits(hdev); /* setting core registers */ hdmi_timing_apply(hdev, conf); /* enable HDMI and timing generator */ hdmi_enable(hdev, 1); hdmi_tg_enable(hdev, 1); hdev->streaming = HDMI_STREAMING; /* change the HPD interrupt: External -> Internal */ disable_irq(hdev->ext_irq); cancel_delayed_work_sync(&hdev->hpd_work_ext); hdmi_reg_set_int_hpd(hdev); enable_irq(hdev->int_irq); dev_info(hdev->dev, "HDMI interrupt changed to internal\n"); /* start HDCP if enabled */ if (hdev->hdcp_info.hdcp_enable) { ret = hdcp_start(hdev); if (ret) return ret; } val0 = hdmi_read(hdev, HDMI_ACR_MCTS0); val1 = hdmi_read(hdev, HDMI_ACR_MCTS1); val2 = hdmi_read(hdev, HDMI_ACR_MCTS2); dev_dbg(dev, "HDMI_ACR_MCTS0 : 0x%08x\n", val0); dev_dbg(dev, "HDMI_ACR_MCTS1 : 0x%08x\n", val1); dev_dbg(dev, "HDMI_ACR_MCTS2 : 0x%08x\n", val2); hdmi_dumpregs(hdev, "streamon"); return 0; }
int tpi_set_bit(struct hdmi_info *hdmi, u8 reg, u8 pattern) { return hdmi_write_byte(hdmi->client, reg, hdmi_read(hdmi->client, reg) | pattern); }
void tpi_clear_bit(struct hdmi_info *hdmi, u8 reg, u8 pattern) { hdmi_write_byte(hdmi->client, reg, hdmi_read(hdmi->client, reg) & pattern); }
static int hdmi_streamon(struct hdmi_device *hdev) { struct device *dev = hdev->dev; struct hdmi_resources *res = &hdev->res; int ret, tries; u32 val0, val1, val2; dev_dbg(dev, "%s\n", __func__); hdev->streaming = 1; ret = v4l2_subdev_call(hdev->phy_sd, video, s_stream, 1); if (ret) return ret; /* waiting for HDMIPHY's PLL to get to steady state */ for (tries = 100; tries; --tries) { if (is_hdmiphy_ready(hdev)) break; mdelay(1); } /* steady state not achieved */ if (tries == 0) { dev_err(dev, "hdmiphy's pll could not reach steady state.\n"); v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0); hdmi_dumpregs(hdev, "s_stream"); return -EIO; } /* hdmiphy clock is used for HDMI in streaming mode */ clk_disable(res->sclk_hdmi); clk_set_parent(res->sclk_hdmi, res->sclk_hdmiphy); clk_enable(res->sclk_hdmi); /* 3D test */ hdmi_set_infoframe(hdev); /* set packets for audio */ hdmi_set_packets(hdev); /* init audio */ #if defined(CONFIG_VIDEO_EXYNOS_HDMI_AUDIO_I2S) hdmi_reg_i2s_audio_init(hdev); #elif defined(CONFIG_VIDEO_EXYNOS_HDMI_AUDIO_SPDIF) hdmi_reg_spdif_audio_init(hdev); #endif /* enbale HDMI audio */ if (hdev->audio_enable) hdmi_audio_enable(hdev, 1); hdmi_set_dvi_mode(hdev); /* enable HDMI and timing generator */ hdmi_enable(hdev, 1); hdmi_tg_enable(hdev, 1); mdelay(5); val0 = hdmi_read(hdev, HDMI_ACR_MCTS0); val1 = hdmi_read(hdev, HDMI_ACR_MCTS1); val2 = hdmi_read(hdev, HDMI_ACR_MCTS2); dev_dbg(dev, "HDMI_ACR_MCTS0 : 0x%08x\n", val0); dev_dbg(dev, "HDMI_ACR_MCTS1 : 0x%08x\n", val1); dev_dbg(dev, "HDMI_ACR_MCTS2 : 0x%08x\n", val2); /* start HDCP if enabled */ if (hdev->hdcp_info.hdcp_enable) { ret = hdcp_start(hdev); if (ret) return ret; } hdmi_dumpregs(hdev, "streamon"); return 0; }
static int __init sh_hdmi_probe(struct platform_device *pdev) { struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); int irq = platform_get_irq(pdev, 0), ret; struct sh_hdmi *hdmi; long rate; if (!res || !pdata || irq < 0) return -ENODEV; hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL); if (!hdmi) { dev_err(&pdev->dev, "Cannot allocate device data\n"); return -ENOMEM; } hdmi->dev = &pdev->dev; hdmi->hdmi_clk = clk_get(&pdev->dev, "ick"); if (IS_ERR(hdmi->hdmi_clk)) { ret = PTR_ERR(hdmi->hdmi_clk); dev_err(&pdev->dev, "Unable to get clock: %d\n", ret); goto egetclk; } rate = PICOS2KHZ(pdata->lcd_chan->lcd_cfg.pixclock) * 1000; rate = clk_round_rate(hdmi->hdmi_clk, rate); if (rate < 0) { ret = rate; dev_err(&pdev->dev, "Cannot get suitable rate: %ld\n", rate); goto erate; } ret = clk_set_rate(hdmi->hdmi_clk, rate); if (ret < 0) { dev_err(&pdev->dev, "Cannot set rate %ld: %d\n", rate, ret); goto erate; } pr_debug("HDMI set frequency %lu\n", rate); ret = clk_enable(hdmi->hdmi_clk); if (ret < 0) { dev_err(&pdev->dev, "Cannot enable clock: %d\n", ret); goto eclkenable; } dev_info(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate); if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) { dev_err(&pdev->dev, "HDMI register region already claimed\n"); ret = -EBUSY; goto ereqreg; } hdmi->base = ioremap(res->start, resource_size(res)); if (!hdmi->base) { dev_err(&pdev->dev, "HDMI register region already claimed\n"); ret = -ENOMEM; goto emap; } platform_set_drvdata(pdev, hdmi); /* Product and revision IDs are 0 in sh-mobile version */ dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n", hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID)); /* Set up LCDC callbacks */ pdata->lcd_chan->board_cfg.board_data = hdmi; pdata->lcd_chan->board_cfg.display_on = hdmi_display_on; pdata->lcd_chan->board_cfg.display_off = hdmi_display_off; INIT_DELAYED_WORK(&hdmi->edid_work, edid_work_fn); pm_runtime_enable(&pdev->dev); pm_runtime_resume(&pdev->dev); ret = request_irq(irq, sh_hdmi_hotplug, 0, dev_name(&pdev->dev), hdmi); if (ret < 0) { dev_err(&pdev->dev, "Unable to request irq: %d\n", ret); goto ereqirq; } return 0; ereqirq: pm_runtime_disable(&pdev->dev); iounmap(hdmi->base); emap: release_mem_region(res->start, resource_size(res)); ereqreg: clk_disable(hdmi->hdmi_clk); eclkenable: erate: clk_put(hdmi->hdmi_clk); egetclk: kfree(hdmi); return ret; }
static int hdmi_pll_enable(struct clk_hw *hw) { struct hdmi_phy_8960 *phy_8960 = clk_to_phy(hw); struct hdmi *hdmi = phy_8960->hdmi; int timeout_count, pll_lock_retry = 10; unsigned int val; DBG(""); /* Assert PLL S/W reset */ hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x8d); hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0, 0x10); hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1, 0x1a); /* Wait for a short time before de-asserting * to allow the hardware to complete its job. * This much of delay should be fine for hardware * to assert and de-assert. */ udelay(10); /* De-assert PLL S/W reset */ hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x0d); val = hdmi_read(hdmi, REG_HDMI_8960_PHY_REG12); val |= HDMI_8960_PHY_REG12_SW_RESET; /* Assert PHY S/W reset */ hdmi_write(hdmi, REG_HDMI_8960_PHY_REG12, val); val &= ~HDMI_8960_PHY_REG12_SW_RESET; /* Wait for a short time before de-asserting to allow the hardware to complete its job. This much of delay should be fine for hardware to assert and de-assert. */ udelay(10); /* De-assert PHY S/W reset */ hdmi_write(hdmi, REG_HDMI_8960_PHY_REG12, val); hdmi_write(hdmi, REG_HDMI_8960_PHY_REG2, 0x3f); val = hdmi_read(hdmi, REG_HDMI_8960_PHY_REG12); val |= HDMI_8960_PHY_REG12_PWRDN_B; hdmi_write(hdmi, REG_HDMI_8960_PHY_REG12, val); /* Wait 10 us for enabling global power for PHY */ mb(); udelay(10); val = hdmi_read(hdmi, REG_HDMI_8960_PHY_PLL_PWRDN_B); val |= HDMI_8960_PHY_PLL_PWRDN_B_PLL_PWRDN_B; val &= ~HDMI_8960_PHY_PLL_PWRDN_B_PD_PLL; hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_PWRDN_B, val); hdmi_write(hdmi, REG_HDMI_8960_PHY_REG2, 0x80); timeout_count = 1000; while (--pll_lock_retry > 0) { /* are we there yet? */ val = hdmi_read(hdmi, REG_HDMI_8960_PHY_PLL_STATUS0); if (val & HDMI_8960_PHY_PLL_STATUS0_PLL_LOCK) break; udelay(1); if (--timeout_count > 0) continue; /* * PLL has still not locked. * Do a software reset and try again * Assert PLL S/W reset first */ hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x8d); udelay(10); hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x0d); /* * Wait for a short duration for the PLL calibration * before checking if the PLL gets locked */ udelay(350); timeout_count = 1000; } return 0; }
static enum drm_connector_status detect_reg(struct hdmi *hdmi) { uint32_t hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS); return (hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED) ? connector_status_connected : connector_status_disconnected; }
int msm_hdmi_hpd_enable(struct drm_connector *connector) { struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector); struct hdmi *hdmi = hdmi_connector->hdmi; const struct hdmi_platform_config *config = hdmi->config; struct device *dev = &hdmi->pdev->dev; uint32_t hpd_ctrl; int i, ret; unsigned long flags; for (i = 0; i < config->hpd_reg_cnt; i++) { ret = regulator_enable(hdmi->hpd_regs[i]); if (ret) { dev_err(dev, "failed to enable hpd regulator: %s (%d)\n", config->hpd_reg_names[i], ret); goto fail; } } ret = pinctrl_pm_select_default_state(dev); if (ret) { dev_err(dev, "pinctrl state chg failed: %d\n", ret); goto fail; } ret = gpio_config(hdmi, true); if (ret) { dev_err(dev, "failed to configure GPIOs: %d\n", ret); goto fail; } pm_runtime_get_sync(dev); enable_hpd_clocks(hdmi, true); msm_hdmi_set_mode(hdmi, false); msm_hdmi_phy_reset(hdmi); msm_hdmi_set_mode(hdmi, true); hdmi_write(hdmi, REG_HDMI_USEC_REFTIMER, 0x0001001b); /* enable HPD events: */ hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, HDMI_HPD_INT_CTRL_INT_CONNECT | HDMI_HPD_INT_CTRL_INT_EN); /* set timeout to 4.1ms (max) for hardware debounce */ spin_lock_irqsave(&hdmi->reg_lock, flags); hpd_ctrl = hdmi_read(hdmi, REG_HDMI_HPD_CTRL); hpd_ctrl |= HDMI_HPD_CTRL_TIMEOUT(0x1fff); /* Toggle HPD circuit to trigger HPD sense */ hdmi_write(hdmi, REG_HDMI_HPD_CTRL, ~HDMI_HPD_CTRL_ENABLE & hpd_ctrl); hdmi_write(hdmi, REG_HDMI_HPD_CTRL, HDMI_HPD_CTRL_ENABLE | hpd_ctrl); spin_unlock_irqrestore(&hdmi->reg_lock, flags); return 0; fail: return ret; }
static int read_edid(uint8_t * buf, size_t count) { int r; int i, j; int tries; int edid_ready; uint8_t val; log_debug(&log, "Reading edid...\n"); if (buf == NULL || count < EDID_LEN) { log_warn(&log, "Expected 128 byte data buffer\n"); return -1; } r = hdmi_clear(HDMI_HDCP_OTP_PAGE, HDMI_HDCP_OTP_SOME_REG, HDMI_HDCP_OTP_SOME_MASK); if (r != OK) { log_warn(&log, "Failed to clear bit in HDCP OTP reg\n"); return -1; } /* Enable EDID Block Read Interrupt */ r = hdmi_set(HDMI_CTRL_PAGE, HDMI_CTRL_INT_REG, HDMI_CTRL_INT_EDID_MASK); if (r != OK) { log_warn(&log, "Failed to enable EDID Block Read interrupt\n"); return -1; } /* enable global interrupts */ r = hdmi_write(HDMI_CTRL_PAGE, HDMI_CTRL_INTR_CTRL_REG, HDMI_CTRL_INTR_EN_GLO_MASK); if (r != OK) { log_warn(&log, "Failed to enable interrupts\n"); return -1; } /* Set Device Address */ r = hdmi_write(HDMI_EDID_PAGE, HDMI_EDID_DEV_ADDR_REG, HDMI_EDID_DEV_ADDR); if (r != OK) { log_warn(&log, "Couldn't set device address\n"); return -1; } /* Set Offset */ r = hdmi_write(HDMI_EDID_PAGE, HDMI_EDID_OFFSET_REG, HDMI_EDID_OFFSET); if (r != OK) { log_warn(&log, "Couldn't set offset\n"); return -1; } /* Set Segment Pointer Address */ r = hdmi_write(HDMI_EDID_PAGE, HDMI_EDID_SEG_PTR_ADDR_REG, HDMI_EDID_SEG_PTR_ADDR); if (r != OK) { log_warn(&log, "Couldn't set segment pointer address\n"); return -1; } /* Set Segment Address */ r = hdmi_write(HDMI_EDID_PAGE, HDMI_EDID_SEG_ADDR_REG, HDMI_EDID_SEG_ADDR); if (r != OK) { log_warn(&log, "Couldn't set segment address\n"); return -1; } /* * Toggle EDID Read Request Bit to request a read. */ r = hdmi_write(HDMI_EDID_PAGE, HDMI_EDID_REQ_REG, HDMI_EDID_REQ_READ_MASK); if (r != OK) { log_warn(&log, "Couldn't set Read Request bit\n"); return -1; } r = hdmi_write(HDMI_EDID_PAGE, HDMI_EDID_REQ_REG, 0x00); if (r != OK) { log_warn(&log, "Couldn't clear Read Request bit\n"); return -1; } log_debug(&log, "Starting polling\n"); /* poll interrupt status flag */ edid_ready = 0; for (tries = 0; tries < 100; tries++) { r = hdmi_read(HDMI_CTRL_PAGE, HDMI_CTRL_INT_REG, &val); if (r != OK) { log_warn(&log, "Read failed while polling int flag\n"); return -1; } if (val & HDMI_CTRL_INT_EDID_MASK) { log_debug(&log, "Mask Set\n"); edid_ready = 1; break; } micro_delay(1000); } if (!edid_ready) { log_warn(&log, "Data Ready interrupt never fired.\n"); return EBUSY; } log_debug(&log, "Ready to read\n"); /* Finally, perform the read. */ memset(buf, '\0', count); r = hdmi_read_block(HDMI_EDID_PAGE, HDMI_EDID_DATA_REG, buf, EDID_LEN); if (r != OK) { log_warn(&log, "Failed to read EDID data\n"); return -1; } /* Disable EDID Block Read Interrupt */ r = hdmi_clear(HDMI_CTRL_PAGE, HDMI_CTRL_INT_REG, HDMI_CTRL_INT_EDID_MASK); if (r != OK) { log_warn(&log, "Failed to disable EDID Block Read interrupt\n"); return -1; } r = hdmi_set(HDMI_HDCP_OTP_PAGE, HDMI_HDCP_OTP_SOME_REG, HDMI_HDCP_OTP_SOME_MASK); if (r != OK) { log_warn(&log, "Failed to set bit in HDCP/OTP reg\n"); return -1; } log_debug(&log, "Done EDID Reading\n"); return OK; }
int bsp_hdmi_ddc_read(char cmd,char pointer,char offset,int nbyte,char * pbuf) { unsigned char off = offset; unsigned int to_cnt; int ret = 0; hdmi_write(0x10010,0x45); hdmi_write(0x10011,0x45); hdmi_write(0x10012,0x52); hdmi_write(0x10013,0x54); hdmi_write(0x4EE1, 0x00); to_cnt = 50; while((hdmi_read(0x4EE1)&0x01)!=0x01) { hdmi_udelay(10); to_cnt--; //wait for 500us for timeout if(to_cnt == 0) { pr_warn("ddc rst timeout\n"); break; } } hdmi_write(0x8EE3, 0x05); hdmi_write(0x0EE3, 0x08); hdmi_write(0x4EE2, 0xd8); hdmi_write(0xCEE2, 0xfe); to_cnt = 10; while(nbyte > 0) { to_cnt = 10; hdmi_write(0x0EE0, 0xa0 >> 1); hdmi_write(0x0EE1, off); hdmi_write(0x4EE0, 0x60 >> 1); hdmi_write(0xCEE0, pointer); hdmi_write(0x0EE2, 0x02); while(1) { to_cnt--; //wait for 10ms for timeout if(to_cnt == 0) { pr_warn("ddc read timeout, byte cnt = %d\n",nbyte); break; } if( (hdmi_read(0x0013) & 0x02) == 0x02) { hdmi_write(0x0013, hdmi_read(0x0013) & 0x02); * pbuf++ = hdmi_read(0x8EE1); break; } else if( (hdmi_read(0x0013) & 0x01) == 0x01) { hdmi_write(0x0013, hdmi_read(0x0013) & 0x01); ret = -1; break; } hdmi_udelay(1000); } nbyte --; off ++; } hdmi_write(0x10010,0x52); hdmi_write(0x10011,0x54); hdmi_write(0x10012,0x41); hdmi_write(0x10013,0x57); return ret; }
static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id) { struct sh_hdmi *hdmi = dev_id; u8 status1, status2, mask1, mask2; /* mode_b and PLLA and PLLB reset */ hdmi_write(hdmi, 0x2C, HDMI_SYSTEM_CTRL); /* How long shall reset be held? */ udelay(10); /* mode_b and PLLA and PLLB reset release */ hdmi_write(hdmi, 0x20, HDMI_SYSTEM_CTRL); status1 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_1); status2 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_2); mask1 = hdmi_read(hdmi, HDMI_INTERRUPT_MASK_1); mask2 = hdmi_read(hdmi, HDMI_INTERRUPT_MASK_2); /* Correct would be to ack only set bits, but the datasheet requires 0xff */ hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_1); hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_2); if (printk_ratelimit()) pr_debug("IRQ #%d: Status #1: 0x%x & 0x%x, #2: 0x%x & 0x%x\n", irq, status1, mask1, status2, mask2); if (!((status1 & mask1) | (status2 & mask2))) { return IRQ_NONE; } else if (status1 & 0xc0) { u8 msens; /* Datasheet specifies 10ms... */ udelay(500); msens = hdmi_read(hdmi, HDMI_HOT_PLUG_MSENS_STATUS); pr_debug("MSENS 0x%x\n", msens); /* Check, if hot plug & MSENS pin status are both high */ if ((msens & 0xC0) == 0xC0) { /* Display plug in */ hdmi->hp_state = HDMI_HOTPLUG_CONNECTED; /* Set EDID word address */ hdmi_write(hdmi, 0x00, HDMI_EDID_WORD_ADDRESS); /* Set EDID segment pointer */ hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER); /* Enable EDID interrupt */ hdmi_write(hdmi, 0xC6, HDMI_INTERRUPT_MASK_1); } else if (!(status1 & 0x80)) { /* Display unplug, beware multiple interrupts */ if (hdmi->hp_state != HDMI_HOTPLUG_DISCONNECTED) schedule_delayed_work(&hdmi->edid_work, 0); hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED; /* display_off will switch back to mode_a */ } } else if (status1 & 2) { /* EDID error interrupt: retry */ /* Set EDID word address */ hdmi_write(hdmi, 0x00, HDMI_EDID_WORD_ADDRESS); /* Set EDID segment pointer */ hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER); } else if (status1 & 4) { /* Disable EDID interrupt */ hdmi_write(hdmi, 0xC0, HDMI_INTERRUPT_MASK_1); hdmi->hp_state = HDMI_HOTPLUG_EDID_DONE; schedule_delayed_work(&hdmi->edid_work, msecs_to_jiffies(10)); } return IRQ_HANDLED; }
{ .addr = 0x30, .flags = 0, .len = 1, .buf = &pbuf[2], }, { .addr = 0x50, .flags = 0, .len = 1, .buf = &pbuf[3], }, { //Block-3 .addr = 0x50, .flags = I2C_M_RD, .len = 128, .buf = &hdmi->edid_buf[384], }, }; HDMI_DBG("%s\n", __func__); #if 0 DisableTMDS(hdmi); #else val = hdmi_read(hdmi->client, TPI_SYSTEM_CONTROL); //hdmi_write_byte(hdmi->client, TPI_SYSTEM_CONTROL, val|BIT_4|BIT_6); hdmi_write_byte(hdmi->client, TPI_SYSTEM_CONTROL, val|BIT_4); #endif if (!GetDDC_Access(hdmi, &SysCtrlReg)) { pr_err("%s: DDC bus request failed\n", __func__); return DDC_BUS_REQ_FAILURE; } // Block-0 memset(hdmi->edid_buf, 0, 512); msg.addr = 0x50; msg.flags = 0; msg.len = 1;
int bsp_hdmi_video(struct video_para *video) { unsigned int id = get_vid(video->vic); glb_video.vic = video->vic; switch(glb_video.vic) { case 2: case 4: case 6: case 17: case 19: case 21: video->csc = BT601; break; default: video->csc = BT709; break; } if(hdmi_phy_set(video)!=0) return -1; bsp_hdmi_inner_init(); hdmi_write(0x0840, 0x01); hdmi_write(0x4845, 0x00); hdmi_write(0x0040, ptbl[id].para[3] | 0x10); hdmi_write(0x10001, ( (ptbl[id].para[3] < 96) ? 0x03 : 0x00 ) ); hdmi_write(0x8040, ptbl[id].para[4]); hdmi_write(0x4043, ptbl[id].para[5]); hdmi_write(0x8042, ptbl[id].para[6]); hdmi_write(0x0042, ptbl[id].para[7]); hdmi_write(0x4042, ptbl[id].para[8]); hdmi_write(0x4041, ptbl[id].para[9]); hdmi_write(0xC041, ptbl[id].para[10]); hdmi_write(0x0041, ptbl[id].para[11]); hdmi_write(0x8041, ptbl[id].para[12]); hdmi_write(0x4040, ptbl[id].para[13]); hdmi_write(0xC040, ptbl[id].para[14]); hdmi_write(0x0043, ptbl[id].para[15]); hdmi_write(0x8043, ptbl[id].para[16]); hdmi_write(0x0045, 0x0c); hdmi_write(0x8044, 0x20); hdmi_write(0x8045, 0x01); hdmi_write(0x0046, 0x0b); hdmi_write(0x0047, 0x16); hdmi_write(0x8046, 0x21); hdmi_write(0x3048, ptbl[id].para[2] ? 0x21 : 0x10); hdmi_write(0x0401, ptbl[id].para[2] ? 0x41 : 0x40); hdmi_write(0x8400, 0x07); hdmi_write(0x8401, 0x00); hdmi_write(0x0402, 0x47); hdmi_write(0x0800, 0x01); hdmi_write(0x0801, 0x07); hdmi_write(0x8800, 0x00); hdmi_write(0x8801, 0x00); hdmi_write(0x0802, 0x00); hdmi_write(0x0803, 0x00); hdmi_write(0x8802, 0x00); hdmi_write(0x8803, 0x00); if(video->is_hdmi) { hdmi_write(0xB045, 0x08); hdmi_write(0x2045, 0x00); hdmi_write(0x2044, 0x0c); hdmi_write(0x6041, 0x03); hdmi_write(0xA044, ((ptbl[id].para[0]&0x100) == 0x100) ? 0x20 : ( ((ptbl[id].para[0]&0x80) == 0x80) ? 0x40 : 0x00) ); hdmi_write(0xA045, ((ptbl[id].para[0]&0x100) == 0x100) ? (ptbl[id].para[0]&0x7f) : 0x00); hdmi_write(0x2046, 0x00); hdmi_write(0x3046, 0x01); hdmi_write(0x3047, 0x11); hdmi_write(0x4044, 0x00); hdmi_write(0x0052, 0x00); hdmi_write(0x8051, 0x11); hdmi_write(0x10010,0x45); hdmi_write(0x10011,0x45); hdmi_write(0x10012,0x52); hdmi_write(0x10013,0x54); hdmi_write(0x0040, hdmi_read(0x0040) | 0x08 ); hdmi_write(0x10010,0x52); hdmi_write(0x10011,0x54); hdmi_write(0x10012,0x41); hdmi_write(0x10013,0x57); hdmi_write(0x4045, video->is_yuv ? 0x02 : 0x00); if(ptbl[id].para[17] == 0) hdmi_write(0xC044, (video->csc << 6) | 0x18); else if(ptbl[id].para[17] == 1) hdmi_write(0xC044, (video->csc << 6) | 0x28); else hdmi_write(0xC044, (video->csc << 6) | 0x08); if((ptbl[id].para[0] == 32) || (ptbl[id].para[0] == 160)|| (ptbl[id].para[0] == 257)|| (ptbl[id].para[0] == 258)) { hdmi_write(0xC045, 0x01); } else { hdmi_write(0xC045, 0x00); } hdmi_write(0x4046, ptbl[id].para[0]&0x7f); } if(video->is_hcts) { hdmi_write(0x00C0, video->is_hdmi ? 0x91 : 0x90 ); hdmi_write(0x00C1, 0x05); hdmi_write(0x40C1, (ptbl[id].para[3] < 96) ? 0x10 : 0x1a); hdmi_write(0x80C2, 0xff); hdmi_write(0x40C0, 0xfd); hdmi_write(0xC0C0, 0x40); hdmi_write(0x00C1, 0x04); hdmi_write(0x10010,0x45); hdmi_write(0x10011,0x45); hdmi_write(0x10012,0x52); hdmi_write(0x10013,0x54); hdmi_write(0x0040, hdmi_read(0x0040) | 0x80 ); hdmi_write(0x00C0, video->is_hdmi ? 0x95 : 0x94 ); hdmi_write(0x10010,0x52); hdmi_write(0x10011,0x54); hdmi_write(0x10012,0x41); hdmi_write(0x10013,0x57); } hdmi_write(0x0082, 0x00); hdmi_write(0x0081, 0x00); hdmi_write(0x0840, 0x00); if(video->is_hcts) { } return 0; }
static int hpd_enable(struct hdmi_connector *hdmi_connector) { struct hdmi *hdmi = hdmi_connector->hdmi; struct drm_device *dev = hdmi_connector->base.dev; struct hdmi_phy *phy = hdmi->phy; uint32_t hpd_ctrl; int ret; ret = gpio_config(hdmi, true); if (ret) { dev_err(dev->dev, "failed to configure GPIOs: %d\n", ret); goto fail; } ret = clk_prepare_enable(hdmi->clk); if (ret) { dev_err(dev->dev, "failed to enable 'clk': %d\n", ret); goto fail; } ret = clk_prepare_enable(hdmi->m_pclk); if (ret) { dev_err(dev->dev, "failed to enable 'm_pclk': %d\n", ret); goto fail; } ret = clk_prepare_enable(hdmi->s_pclk); if (ret) { dev_err(dev->dev, "failed to enable 's_pclk': %d\n", ret); goto fail; } if (hdmi->mpp0) ret = regulator_enable(hdmi->mpp0); if (!ret) ret = regulator_enable(hdmi->mvs); if (ret) { dev_err(dev->dev, "failed to enable regulators: %d\n", ret); goto fail; } hdmi_set_mode(hdmi, false); phy->funcs->reset(phy); hdmi_set_mode(hdmi, true); hdmi_write(hdmi, REG_HDMI_USEC_REFTIMER, 0x0001001b); /* enable HPD events: */ hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, HDMI_HPD_INT_CTRL_INT_CONNECT | HDMI_HPD_INT_CTRL_INT_EN); /* set timeout to 4.1ms (max) for hardware debounce */ hpd_ctrl = hdmi_read(hdmi, REG_HDMI_HPD_CTRL); hpd_ctrl |= HDMI_HPD_CTRL_TIMEOUT(0x1fff); /* Toggle HPD circuit to trigger HPD sense */ hdmi_write(hdmi, REG_HDMI_HPD_CTRL, ~HDMI_HPD_CTRL_ENABLE & hpd_ctrl); hdmi_write(hdmi, REG_HDMI_HPD_CTRL, HDMI_HPD_CTRL_ENABLE | hpd_ctrl); return 0; fail: return ret; }