static int dpi_set_mode(struct omap_overlay_manager *mgr) { struct omap_video_timings *t = &dpi.timings; int lck_div = 0, pck_div = 0; unsigned long fck = 0; unsigned long pck; int r = 0; if (dpi.dsidev) r = dpi_set_dsi_clk(mgr->id, t->pixel_clock * 1000, &fck, &lck_div, &pck_div); else r = dpi_set_dispc_clk(t->pixel_clock * 1000, &fck, &lck_div, &pck_div); if (r) return r; pck = fck / lck_div / pck_div / 1000; if (pck != t->pixel_clock) { DSSWARN("Could not find exact pixel clock. " "Requested %d kHz, got %lu kHz\n", t->pixel_clock, pck); t->pixel_clock = pck; } dss_mgr_set_timings(mgr, t); return 0; }
static int rfbi_transfer_area(struct omap_dss_device *dssdev, void (*callback)(void *data), void *data) { u32 l; int r; struct omap_overlay_manager *mgr = rfbi.output.manager; u16 width = rfbi.timings.x_res; u16 height = rfbi.timings.y_res; /*BUG_ON(callback == 0);*/ BUG_ON(rfbi.framedone_callback != NULL); DSSDBG("rfbi_transfer_area %dx%d\n", width, height); dss_mgr_set_timings(mgr, &rfbi.timings); r = dss_mgr_enable(mgr); if (r) return r; rfbi.framedone_callback = callback; rfbi.framedone_callback_data = data; rfbi_write_reg(RFBI_PIXEL_CNT, width * height); l = rfbi_read_reg(RFBI_CONTROL); l = FLD_MOD(l, 1, 0, 0); /* enable */ if (!rfbi.te_enabled) l = FLD_MOD(l, 1, 4, 4); /* ITE */ rfbi_write_reg(RFBI_CONTROL, l); return 0; }
static int rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width, u16 height, void (*callback)(void *data), void *data) { u32 l; int r; struct omap_video_timings timings = { .hsw = 1, .hfp = 1, .hbp = 1, .vsw = 1, .vfp = 0, .vbp = 0, .x_res = width, .y_res = height, }; /*BUG_ON(callback == 0);*/ BUG_ON(rfbi.framedone_callback != NULL); DSSDBG("rfbi_transfer_area %dx%d\n", width, height); dss_mgr_set_timings(dssdev->manager, &timings); r = dss_mgr_enable(dssdev->manager); if (r) return r; rfbi.framedone_callback = callback; rfbi.framedone_callback_data = data; rfbi_write_reg(RFBI_PIXEL_CNT, width * height); l = rfbi_read_reg(RFBI_CONTROL); l = FLD_MOD(l, 1, 0, 0); /* enable */ if (!rfbi.te_enabled) l = FLD_MOD(l, 1, 4, 4); /* ITE */ rfbi_write_reg(RFBI_CONTROL, l); return 0; } static void framedone_callback(void *data, u32 mask) { void (*callback)(void *data); DSSDBG("FRAMEDONE\n"); REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0); callback = rfbi.framedone_callback; rfbi.framedone_callback = NULL; if (callback != NULL) callback(rfbi.framedone_callback_data); }
void dpi_set_timings(struct omap_dss_device *dssdev, struct omap_video_timings *timings) { int r; DSSDBG("dpi_set_timings\n"); dssdev->panel.timings = *timings; if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { r = dispc_runtime_get(); if (r) return; dpi_set_mode(dssdev); dispc_runtime_put(); } else { dss_mgr_set_timings(dssdev->manager, timings); } }
static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) { struct omap_overlay_manager *mgr = rfbi.output.manager; struct dss_lcd_mgr_config mgr_config; mgr_config.io_pad_mode = DSS_IO_PAD_MODE_RFBI; mgr_config.stallmode = true; /* Do we need fifohandcheck for RFBI? */ mgr_config.fifohandcheck = false; mgr_config.video_port_width = rfbi.pixel_size; mgr_config.lcden_sig_polarity = 0; dss_mgr_set_lcd_config(mgr, &mgr_config); /* * Set rfbi.timings with default values, the x_res and y_res fields * are expected to be already configured by the panel driver via * omapdss_rfbi_set_size() */ rfbi.timings.hsw = 1; rfbi.timings.hfp = 1; rfbi.timings.hbp = 1; rfbi.timings.vsw = 1; rfbi.timings.vfp = 0; rfbi.timings.vbp = 0; rfbi.timings.interlace = false; rfbi.timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH; rfbi.timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH; rfbi.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; rfbi.timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH; rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE; dss_mgr_set_timings(mgr, &rfbi.timings); }
static int dpi_set_mode(struct omap_dss_device *dssdev) { struct omap_video_timings *t = &dssdev->panel.timings; int lck_div = 0, pck_div = 0; unsigned long fck = 0; unsigned long pck; bool is_tft; int r = 0; dispc_mgr_set_pol_freq(dssdev->manager->id, dssdev->panel.config, dssdev->panel.acbi, dssdev->panel.acb); is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; if (dpi_use_dsi_pll(dssdev)) r = dpi_set_dsi_clk(dssdev, is_tft, t->pixel_clock * 1000, &fck, &lck_div, &pck_div); else r = dpi_set_dispc_clk(dssdev, is_tft, t->pixel_clock * 1000, &fck, &lck_div, &pck_div); if (r) return r; pck = fck / lck_div / pck_div / 1000; if (pck != t->pixel_clock) { DSSWARN("Could not find exact pixel clock. " "Requested %d kHz, got %lu kHz\n", t->pixel_clock, pck); t->pixel_clock = pck; } dss_mgr_set_timings(dssdev->manager, t); return 0; }
static int hdmi_power_on_full(struct omap_dss_device *dssdev) { int r; struct omap_video_timings *p; struct omap_overlay_manager *mgr = hdmi.output.manager; struct dss_pll_clock_info hdmi_cinfo = { 0 }; r = hdmi_power_on_core(dssdev); if (r) return r; p = &hdmi.cfg.timings; DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res); hdmi_pll_compute(&hdmi.pll, p->pixelclock, &hdmi_cinfo); /* disable and clear irqs */ hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff); hdmi_wp_set_irqstatus(&hdmi.wp, hdmi_wp_get_irqstatus(&hdmi.wp)); r = dss_pll_enable(&hdmi.pll.pll); if (r) { DSSERR("Failed to enable PLL\n"); goto err_pll_enable; } r = dss_pll_set_config(&hdmi.pll.pll, &hdmi_cinfo); if (r) { DSSERR("Failed to configure PLL\n"); goto err_pll_cfg; } r = hdmi_phy_configure(&hdmi.phy, hdmi_cinfo.clkdco, hdmi_cinfo.clkout[0]); if (r) { DSSDBG("Failed to start PHY\n"); goto err_phy_cfg; } r = hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_LDOON); if (r) goto err_phy_pwr; hdmi5_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg); /* bypass TV gamma table */ dispc_enable_gamma_table(0); /* tv size */ dss_mgr_set_timings(mgr, p); r = hdmi_wp_video_start(&hdmi.wp); if (r) goto err_vid_enable; r = dss_mgr_enable(mgr); if (r) goto err_mgr_enable; hdmi_wp_set_irqenable(&hdmi.wp, HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT); return 0; err_mgr_enable: hdmi_wp_video_stop(&hdmi.wp); err_vid_enable: hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF); err_phy_pwr: err_phy_cfg: err_pll_cfg: dss_pll_disable(&hdmi.pll.pll); err_pll_enable: hdmi_power_off_core(dssdev); return -EIO; }
static int sdi_display_enable(struct omap_dss_device *dssdev) { struct sdi_device *sdi = dssdev_to_sdi(dssdev); struct videomode *vm = &sdi->vm; unsigned long fck; struct dispc_clock_info dispc_cinfo; unsigned long pck; int r; if (!sdi->output.dispc_channel_connected) { DSSERR("failed to enable display: no output/manager\n"); return -ENODEV; } r = regulator_enable(sdi->vdds_sdi_reg); if (r) goto err_reg_enable; r = dispc_runtime_get(sdi->dss->dispc); if (r) goto err_get_dispc; /* 15.5.9.1.2 */ vm->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE | DISPLAY_FLAGS_SYNC_POSEDGE; r = sdi_calc_clock_div(sdi, vm->pixelclock, &fck, &dispc_cinfo); if (r) goto err_calc_clock_div; sdi->mgr_config.clock_info = dispc_cinfo; pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div; if (pck != vm->pixelclock) { DSSWARN("Could not find exact pixel clock. Requested %lu Hz, got %lu Hz\n", vm->pixelclock, pck); vm->pixelclock = pck; } dss_mgr_set_timings(&sdi->output, vm); r = dss_set_fck_rate(sdi->dss, fck); if (r) goto err_set_dss_clock_div; sdi_config_lcd_manager(sdi); /* * LCLK and PCLK divisors are located in shadow registers, and we * normally write them to DISPC registers when enabling the output. * However, SDI uses pck-free as source clock for its PLL, and pck-free * is affected by the divisors. And as we need the PLL before enabling * the output, we need to write the divisors early. * * It seems just writing to the DISPC register is enough, and we don't * need to care about the shadow register mechanism for pck-free. The * exact reason for this is unknown. */ dispc_mgr_set_clock_div(sdi->dss->dispc, sdi->output.dispc_channel, &sdi->mgr_config.clock_info); dss_sdi_init(sdi->dss, sdi->datapairs); r = dss_sdi_enable(sdi->dss); if (r) goto err_sdi_enable; mdelay(2); r = dss_mgr_enable(&sdi->output); if (r) goto err_mgr_enable; return 0; err_mgr_enable: dss_sdi_disable(sdi->dss); err_sdi_enable: err_set_dss_clock_div: err_calc_clock_div: dispc_runtime_put(sdi->dss->dispc); err_get_dispc: regulator_disable(sdi->vdds_sdi_reg); err_reg_enable: return r; }
static int sdi_display_enable(struct omap_dss_device *dssdev) { struct omap_dss_device *out = &sdi.output; struct omap_video_timings *t = &sdi.timings; unsigned long fck; struct dispc_clock_info dispc_cinfo; unsigned long pck; int r; if (out == NULL || out->manager == NULL) { DSSERR("failed to enable display: no output/manager\n"); return -ENODEV; } r = regulator_enable(sdi.vdds_sdi_reg); if (r) goto err_reg_enable; r = dispc_runtime_get(); if (r) goto err_get_dispc; /* 15.5.9.1.2 */ t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; r = sdi_calc_clock_div(t->pixel_clock * 1000, &fck, &dispc_cinfo); if (r) goto err_calc_clock_div; sdi.mgr_config.clock_info = dispc_cinfo; pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div / 1000; if (pck != t->pixel_clock) { DSSWARN("Could not find exact pixel clock. Requested %d kHz, " "got %lu kHz\n", t->pixel_clock, pck); t->pixel_clock = pck; } dss_mgr_set_timings(out->manager, t); r = dss_set_fck_rate(fck); if (r) goto err_set_dss_clock_div; sdi_config_lcd_manager(dssdev); /* * LCLK and PCLK divisors are located in shadow registers, and we * normally write them to DISPC registers when enabling the output. * However, SDI uses pck-free as source clock for its PLL, and pck-free * is affected by the divisors. And as we need the PLL before enabling * the output, we need to write the divisors early. * * It seems just writing to the DISPC register is enough, and we don't * need to care about the shadow register mechanism for pck-free. The * exact reason for this is unknown. */ dispc_mgr_set_clock_div(out->manager->id, &sdi.mgr_config.clock_info); dss_sdi_init(sdi.datapairs); r = dss_sdi_enable(); if (r) goto err_sdi_enable; mdelay(2); r = dss_mgr_enable(out->manager); if (r) goto err_mgr_enable; return 0; err_mgr_enable: dss_sdi_disable(); err_sdi_enable: err_set_dss_clock_div: err_calc_clock_div: dispc_runtime_put(); err_get_dispc: regulator_disable(sdi.vdds_sdi_reg); err_reg_enable: return r; }
static int hdmi_power_on_full(struct omap_dss_device *dssdev) { int r; struct omap_video_timings *p; struct omap_overlay_manager *mgr = dssdev->output->manager; unsigned long phy; r = hdmi_power_on_core(dssdev); if (r) return r; dss_mgr_disable(mgr); p = &hdmi.ip_data.cfg.timings; DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res); phy = p->pixel_clock; hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data); hdmi.ip_data.ops->video_disable(&hdmi.ip_data); /* config the PLL and PHY hdmi_set_pll_pwrfirst */ r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data); if (r) { DSSDBG("Failed to lock PLL\n"); goto err_pll_enable; } r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data); if (r) { DSSDBG("Failed to start PHY\n"); goto err_phy_enable; } hdmi.ip_data.ops->video_configure(&hdmi.ip_data); /* bypass TV gamma table */ dispc_enable_gamma_table(0); /* tv size */ dss_mgr_set_timings(mgr, p); r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data); if (r) goto err_vid_enable; r = dss_mgr_enable(mgr); if (r) goto err_mgr_enable; return 0; err_mgr_enable: hdmi.ip_data.ops->video_disable(&hdmi.ip_data); err_vid_enable: hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); err_phy_enable: hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); err_pll_enable: hdmi_power_off_core(dssdev); return -EIO; }
static int hdmi_power_on(struct omap_dss_device *dssdev) { int r; struct omap_video_timings *p; struct omap_overlay_manager *mgr = dssdev->output->manager; unsigned long phy; gpio_set_value(hdmi.ct_cp_hpd_gpio, 1); gpio_set_value(hdmi.ls_oe_gpio, 1); /* wait 300us after CT_CP_HPD for the 5V power output to reach 90% */ udelay(300); r = regulator_enable(hdmi.vdda_hdmi_dac_reg); if (r) goto err_vdac_enable; r = hdmi_runtime_get(); if (r) goto err_runtime_get; dss_mgr_disable(mgr); p = &hdmi.ip_data.cfg.timings; DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res); phy = p->pixel_clock; hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data); hdmi.ip_data.ops->video_disable(&hdmi.ip_data); /* config the PLL and PHY hdmi_set_pll_pwrfirst */ r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data); if (r) { DSSDBG("Failed to lock PLL\n"); goto err_pll_enable; } r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data); if (r) { DSSDBG("Failed to start PHY\n"); goto err_phy_enable; } hdmi.ip_data.ops->video_configure(&hdmi.ip_data); /* Make selection of HDMI in DSS */ dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK); /* Select the dispc clock source as PRCM clock, to ensure that it is not * DSI PLL source as the clock selected by DSI PLL might not be * sufficient for the resolution selected / that can be changed * dynamically by user. This can be moved to single location , say * Boardfile. */ dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); /* bypass TV gamma table */ dispc_enable_gamma_table(0); /* tv size */ dss_mgr_set_timings(mgr, p); r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data); if (r) goto err_vid_enable; r = dss_mgr_enable(mgr); if (r) goto err_mgr_enable; return 0; err_mgr_enable: hdmi.ip_data.ops->video_disable(&hdmi.ip_data); err_vid_enable: hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); err_phy_enable: hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); err_pll_enable: hdmi_runtime_put(); err_runtime_get: regulator_disable(hdmi.vdda_hdmi_dac_reg); err_vdac_enable: gpio_set_value(hdmi.ct_cp_hpd_gpio, 0); gpio_set_value(hdmi.ls_oe_gpio, 0); return -EIO; }
static int hdmi_power_on_full(struct omap_dss_device *dssdev) { int r; struct omap_video_timings *p; enum omap_channel channel = dssdev->dispc_channel; struct hdmi_wp_data *wp = &hdmi.wp; struct dss_pll_clock_info hdmi_cinfo = { 0 }; unsigned pc; r = hdmi_power_on_core(dssdev); if (r) return r; /* disable and clear irqs */ hdmi_wp_clear_irqenable(wp, 0xffffffff); hdmi_wp_set_irqstatus(wp, 0xffffffff); p = &hdmi.cfg.timings; DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res); pc = p->pixelclock; if (p->double_pixel) pc *= 2; hdmi_pll_compute(&hdmi.pll, pc, &hdmi_cinfo); r = dss_pll_enable(&hdmi.pll.pll); if (r) { DSSERR("Failed to enable PLL\n"); goto err_pll_enable; } r = dss_pll_set_config(&hdmi.pll.pll, &hdmi_cinfo); if (r) { DSSERR("Failed to configure PLL\n"); goto err_pll_cfg; } r = hdmi_phy_configure(&hdmi.phy, hdmi_cinfo.clkdco, hdmi_cinfo.clkout[0]); if (r) { DSSDBG("Failed to configure PHY\n"); goto err_phy_cfg; } r = hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); if (r) goto err_phy_pwr; hdmi4_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg); /* bypass TV gamma table */ dispc_enable_gamma_table(0); /* tv size */ dss_mgr_set_timings(channel, p); r = dss_mgr_enable(channel); if (r) goto err_mgr_enable; r = hdmi_wp_video_start(&hdmi.wp); if (r) goto err_vid_enable; hdmi_wp_set_irqenable(wp, HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT); return 0; err_vid_enable: dss_mgr_disable(channel); err_mgr_enable: hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF); err_phy_pwr: err_phy_cfg: err_pll_cfg: dss_pll_disable(&hdmi.pll.pll); err_pll_enable: hdmi_power_off_core(dssdev); return -EIO; }
static int hdmi_power_on_full(struct omap_dss_device *dssdev) { int r; struct omap_video_timings *p; struct omap_overlay_manager *mgr = hdmi.output.manager; struct dss_pll_clock_info hdmi_cinfo = { 0 }; r = hdmi_power_on_core(dssdev); if (r) return r; p = &hdmi.cfg.timings; DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res); hdmi_pll_compute(&hdmi.pll, p->pixelclock, &hdmi_cinfo); /* disable and clear irqs */ hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff); hdmi_wp_set_irqstatus(&hdmi.wp, hdmi_wp_get_irqstatus(&hdmi.wp)); r = dss_pll_enable(&hdmi.pll.pll); if (r) { DSSERR("Failed to enable PLL\n"); goto err_pll_enable; } r = dss_pll_set_config(&hdmi.pll.pll, &hdmi_cinfo); if (r) { DSSERR("Failed to configure PLL\n"); goto err_pll_cfg; } r = hdmi_phy_configure(&hdmi.phy, hdmi_cinfo.clkdco, hdmi_cinfo.clkout[0]); if (r) { DSSDBG("Failed to start PHY\n"); goto err_phy_cfg; } r = hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_LDOON); if (r) goto err_phy_pwr; hdmi5_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg); /* bypass TV gamma table */ dispc_enable_gamma_table(0); /* tv size */ dss_mgr_set_timings(mgr, p); r = hdmi_wp_video_start(&hdmi.wp); if (r) goto err_vid_enable; /* * XXX Seems that on we easily get a flood of sync-lost errors when * enabling the output. This seems to be related to the time between * HDMI VSYNC and enabling the DISPC output. * * Testing shows that the sync-lost errors do not happen if we enable * the DISPC output very soon after HDMI VBLANK. So wait here for * VBLANK to reduce the chances of sync-losts. */ hdmi_write_reg(hdmi.wp.base, HDMI_WP_IRQSTATUS, HDMI_IRQ_VIDEO_VSYNC); while (true) { u32 v = hdmi_read_reg(hdmi.wp.base, HDMI_WP_IRQSTATUS_RAW); if (v & HDMI_IRQ_VIDEO_VSYNC) break; usleep_range(500, 1000); } r = dss_mgr_enable(mgr); if (r) goto err_mgr_enable; hdmi_wp_set_irqenable(&hdmi.wp, HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT); return 0; err_mgr_enable: hdmi_wp_video_stop(&hdmi.wp); err_vid_enable: hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF); err_phy_pwr: err_phy_cfg: err_pll_cfg: dss_pll_disable(&hdmi.pll.pll); err_pll_enable: hdmi_power_off_core(dssdev); return -EIO; }