int dpi_init(struct platform_device *pdev) { if (cpu_is_omap34xx() && !cpu_is_omap3630()) { dpi.vdds_dsi_reg = dss_get_vdds_dsi(); if (IS_ERR(dpi.vdds_dsi_reg)) { DSSERR("can't get VDDS_DSI regulator\n"); return PTR_ERR(dpi.vdds_dsi_reg); } } return 0; }
void dss_init_overlays(struct platform_device *pdev) { int i, r; num_overlays = dss_feat_get_num_ovls(); overlays = kzalloc(sizeof(struct omap_overlay) * num_overlays, GFP_KERNEL); BUG_ON(overlays == NULL); for (i = 0; i < num_overlays; ++i) { struct omap_overlay *ovl = &overlays[i]; switch (i) { case 0: ovl->name = "gfx"; ovl->id = OMAP_DSS_GFX; break; case 1: ovl->name = "vid1"; ovl->id = OMAP_DSS_VIDEO1; break; case 2: ovl->name = "vid2"; ovl->id = OMAP_DSS_VIDEO2; break; case 3: ovl->name = "vid3"; ovl->id = OMAP_DSS_VIDEO3; break; } ovl->is_enabled = &dss_ovl_is_enabled; ovl->enable = &dss_ovl_enable; ovl->disable = &dss_ovl_disable; ovl->set_manager = &dss_ovl_set_manager; ovl->unset_manager = &dss_ovl_unset_manager; ovl->set_overlay_info = &dss_ovl_set_info; ovl->get_overlay_info = &dss_ovl_get_info; ovl->wait_for_go = &dss_mgr_wait_for_go_ovl; ovl->caps = dss_feat_get_overlay_caps(ovl->id); ovl->supported_modes = dss_feat_get_supported_color_modes(ovl->id); r = kobject_init_and_add(&ovl->kobj, &overlay_ktype, &pdev->dev.kobj, "overlay%d", i); if (r) DSSERR("failed to create sysfs file\n"); } }
void dss_init_device(struct platform_device *pdev, struct omap_dss_device *dssdev) { struct device_attribute *attr; int i; int r; /* create device sysfs files */ i = 0; while ((attr = display_sysfs_attrs[i++]) != NULL) { r = device_create_file(&dssdev->dev, attr); if (r) DSSERR("failed to create sysfs file\n"); } /* create display? sysfs links */ r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj, dev_name(&dssdev->dev)); if (r) DSSERR("failed to create sysfs display link\n"); }
int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info, const struct omap_video_timings *mgr_timings) { u16 outw, outh; u16 dw, dh; dw = mgr_timings->x_res; dh = mgr_timings->y_res; if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { outw = info->width; outh = info->height; } else { if (info->out_width == 0) outw = info->width; else outw = info->out_width; if (info->out_height == 0) outh = info->height; else outh = info->out_height; } if (dw < info->pos_x + outw) { DSSERR("overlay %d horizontally not inside the display area " "(%d + %d >= %d)\n", ovl->id, info->pos_x, outw, dw); return -EINVAL; } if (dh < info->pos_y + outh) { DSSERR("overlay %d vertically not inside the display area " "(%d + %d >= %d)\n", ovl->id, info->pos_y, outh, dh); return -EINVAL; } return 0; }
static int __init omap_dss_register_drivers(void) { int r; int i; r = platform_driver_probe(&omap_dss_driver, omap_dss_probe); if (r) return r; r = dss_init_platform_driver(); if (r) { DSSERR("Failed to initialize DSS platform driver\n"); goto err_dss; } r = dispc_init_platform_driver(); if (r) { DSSERR("Failed to initialize dispc platform driver\n"); goto err_dispc; } /* * It's ok if the output-driver register fails. It happens, for example, * when there is no output-device (e.g. SDI for OMAP4). */ for (i = 0; i < ARRAY_SIZE(dss_output_drv_reg_funcs); ++i) { r = dss_output_drv_reg_funcs[i](); if (r == 0) dss_output_drv_loaded[i] = true; } return 0; err_dispc: dss_uninit_platform_driver(); err_dss: platform_driver_unregister(&omap_dss_driver); return r; }
static void __init hdmi_probe_pdata(struct platform_device *pdev) { struct omap_dss_device *plat_dssdev; struct omap_dss_device *dssdev; struct omap_dss_hdmi_data *priv; int r; plat_dssdev = hdmi_find_dssdev(pdev); if (!plat_dssdev) return; dssdev = dss_alloc_and_init_device(&pdev->dev); if (!dssdev) return; dss_copy_device_pdata(dssdev, plat_dssdev); priv = dssdev->data; hdmi.ct_cp_hpd_gpio = priv->ct_cp_hpd_gpio; hdmi.ls_oe_gpio = priv->ls_oe_gpio; hdmi.hpd_gpio = priv->hpd_gpio; dssdev->channel = OMAP_DSS_CHANNEL_DIGIT; r = hdmi_init_display(dssdev); if (r) { DSSERR("device %s init failed: %d\n", dssdev->name, r); dss_put_device(dssdev); return; } r = dss_add_device(dssdev); if (r) { DSSERR("device %s register failed: %d\n", dssdev->name, r); dss_put_device(dssdev); return; } }
int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy) { struct resource *res; phy_feat = hdmi_phy_get_features(); if (!phy_feat) return -ENODEV; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy"); if (!res) { DSSERR("can't get PHY mem resource\n"); return -EINVAL; } phy->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(phy->base)) { DSSERR("can't ioremap TX PHY\n"); return PTR_ERR(phy->base); } return 0; }
static int omap_dss_unset_manager(struct omap_overlay *ovl) { int r; if (!ovl->manager) { DSSERR("failed to detach overlay: manager not set\n"); return -EINVAL; } if (ovl->info.enabled) { DSSERR("overlay has to be disabled to unset the manager\n"); return -EINVAL; } r = ovl->wait_for_go(ovl); if (r) return r; ovl->manager = NULL; return 0; }
int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy) { struct resource *res; struct resource temp_res; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi_txphy"); if (!res) { DSSDBG("can't get PHY mem resource by name\n"); /* * if hwmod/DT doesn't have the memory resource information * split into HDMI sub blocks by name, we try again by getting * the platform's first resource. this code will be removed when * the driver can get the mem resources by name */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { DSSERR("can't get PHY mem resource\n"); return -EINVAL; } temp_res.start = res->start + PHY_OFFSET; temp_res.end = temp_res.start + PHY_SIZE - 1; res = &temp_res; } phy->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!phy->base) { DSSERR("can't ioremap TX PHY\n"); return -ENOMEM; } phy->irq = platform_get_irq(pdev, 0); if (phy->irq < 0) { DSSERR("platform_get_irq failed\n"); return -ENODEV; } return 0; }
void dss_restore_context(void) { if (_omap_dss_wait_reset()) DSSERR("DSS not coming out of reset after sleep\n"); RR(SYSCONFIG); RR(CONTROL); #ifdef CONFIG_OMAP2_DSS_SDI RR(SDI_CONTROL); RR(PLL_CONTROL); #endif }
static int omap_hdmihw_probe(struct platform_device *pdev) { int r; r = hdmi_init(pdev); if (r) { DSSERR("Failed to initialize hdmi\n"); goto err_hdmi; } return 0; err_hdmi: return r; }
static void dispc_mgr_disable_lcd_out(enum omap_channel channel) { DECLARE_COMPLETION_ONSTACK(framedone_compl); int r; u32 irq; if (dispc_mgr_is_enabled(channel) == false) return; /* * When we disable LCD output, we need to wait for FRAMEDONE to know * that DISPC has finished with the LCD output. */ irq = dispc_mgr_get_framedone_irq(channel); r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl, irq); if (r) DSSERR("failed to register FRAMEDONE isr\n"); dispc_mgr_enable(channel, false); /* if we couldn't register for framedone, just sleep and exit */ if (r) { msleep(100); return; } if (!wait_for_completion_timeout(&framedone_compl, msecs_to_jiffies(100))) DSSERR("timeout waiting for FRAME DONE\n"); r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl, irq); if (r) DSSERR("failed to unregister FRAMEDONE isr\n"); }
int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) { struct omap_dss_output *out = dssdev->output; int r = 0; DSSDBG("ENTER hdmi_display_enable\n"); mutex_lock(&hdmi.lock); if (out == NULL || out->manager == NULL) { DSSERR("failed to enable display: no output/manager\n"); r = -ENODEV; goto err0; } hdmi.ip_data.hpd_gpio = hdmi.hpd_gpio; r = omap_dss_start_device(dssdev); if (r) { DSSERR("failed to start device\n"); goto err0; } r = hdmi_power_on_full(dssdev); if (r) { DSSERR("failed to power on device\n"); goto err1; } mutex_unlock(&hdmi.lock); return 0; err1: omap_dss_stop_device(dssdev); err0: mutex_unlock(&hdmi.lock); return r; }
static void __init dpi_probe_pdata(struct platform_device *pdev) { struct omap_dss_board_info *pdata = pdev->dev.platform_data; int i, r; for (i = 0; i < pdata->num_devices; ++i) { struct omap_dss_device *dssdev = pdata->devices[i]; if (dssdev->type != OMAP_DISPLAY_TYPE_DPI) continue; r = dpi_init_display(dssdev); if (r) { DSSERR("device %s init failed: %d\n", dssdev->name, r); continue; } r = omap_dss_register_device(dssdev, &pdev->dev, i); if (r) DSSERR("device %s register failed: %d\n", dssdev->name, r); } }
static int _omap_dss_wait_reset(void) { unsigned timeout = 1000; while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) { udelay(1); if (!--timeout) { DSSERR("soft reset failed\n"); return -ENODEV; } } return 0; }
static int omap_dsi2hw_probe(struct platform_device *pdev) { int r; r = dsi2_init(pdev); if (r) { DSSERR("Failed to initialize dsi2\n"); goto err_dsi2; } return 0; err_dsi2: return r; }
int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll) { int r; struct resource *res; r = hdmi_pll_init_features(pdev); if (r) return r; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi_pllctrl"); if (!res) { DSSERR("can't get PLL CTRL IORESOURCE_MEM HDMI\n"); return -EINVAL; } pll->base = devm_request_and_ioremap(&pdev->dev, res); if (!pll->base) { DSSERR("can't ioremap PLL ctrl\n"); return -ENOMEM; } return 0; }
/* PLL_PWR_CMD */ int hdmi_wp_set_pll_pwr(struct hdmi_wp_data *wp, enum hdmi_pll_pwr val) { /* Command for power control of HDMI PLL */ REG_FLD_MOD(wp->base, HDMI_WP_PWR_CTRL, val, 3, 2); /* wait till PHY_PWR_STATUS is set */ if (hdmi_wait_for_bit_change(wp->base, HDMI_WP_PWR_CTRL, 1, 0, val) != val) { DSSERR("Failed to set PLL_PWR_STATUS\n"); return -ETIMEDOUT; } return 0; }
static int _omap_dss_wait_reset(void) { int t = 0; while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) { if (++t > 1000) { DSSERR("soft reset failed\n"); return -ENODEV; } udelay(1); } return 0; }
static int dpi_display_enable(struct omap_display *display) { struct omap_panel *panel = display->panel; int r; if (display->state != OMAP_DSS_DISPLAY_DISABLED) { DSSERR("display already enabled\n"); return -EINVAL; } dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); r = dpi_basic_init(display); if (r) goto err0; #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL dss_clk_enable(DSS_CLK_FCK2); r = dsi_pll_init(0, 1); if (r) goto err1; #endif r = dpi_set_mode(display); if (r) goto err2; mdelay(2); dispc_enable_lcd_out(1); r = panel->enable(display); if (r) goto err3; display->state = OMAP_DSS_DISPLAY_ACTIVE; return 0; err3: dispc_enable_lcd_out(0); err2: #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL dsi_pll_uninit(); err1: dss_clk_disable(DSS_CLK_FCK2); #endif err0: dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); return r; }
static int omap_dispchw_probe(struct platform_device *pdev) { int r; r = dispc_init(pdev); if (r) { DSSERR("Failed to initialize dispc\n"); goto err_dispc; } return 0; err_dispc: return r; }
static int hdmi_get_clocks(struct platform_device *pdev) { struct clk *clk; clk = clk_get(&pdev->dev, "sys_clk"); if (IS_ERR(clk)) { DSSERR("can't get sys_clk\n"); return PTR_ERR(clk); } hdmi.sys_clk = clk; return 0; }
int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll) { int r; struct resource *res; r = hdmi_pll_init_features(pdev); if (r) return r; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll"); if (!res) { DSSERR("can't get PLL mem resource\n"); return -EINVAL; } pll->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(pll->base)) { DSSERR("can't ioremap PLLCTRL\n"); return PTR_ERR(pll->base); } return 0; }
static int hdmi_pll_reset(struct hdmi_pll_data *pll) { /* SYSRESET controlled by power FSM */ REG_FLD_MOD(pll->base, PLLCTRL_PLL_CONTROL, pll_feat->sys_reset, 3, 3); /* READ 0x0 reset is in progress */ if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) { DSSERR("Failed to sysreset PLL\n"); return -ETIMEDOUT; } return 0; }
int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) { int r; r = omap_dss_start_device(dssdev); if (r) { DSSERR("failed to start device\n"); goto err0; } r = omap_dispc_register_isr(framedone_callback, NULL, DISPC_IRQ_FRAMEDONE); if (r) { DSSERR("can't get FRAMEDONE irq\n"); goto err1; } dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT); dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_RFBI); dispc_set_tft_data_lines(dssdev->ctrl.pixel_size); rfbi_configure(dssdev->phy.rfbi.channel, dssdev->ctrl.pixel_size, dssdev->phy.rfbi.data_lines); rfbi_set_timings(dssdev->phy.rfbi.channel, &dssdev->ctrl.rfbi_timings); return 0; err1: omap_dss_stop_device(dssdev); err0: return r; }
static int omap_dss_set_manager(struct omap_overlay *ovl, struct omap_overlay_manager *mgr) { if (!mgr) return -EINVAL; if (ovl->manager) { dump_stack(); DSSERR("overlay '%s' already has a manager '%s'\n", ovl->name, ovl->manager->name); return -EINVAL; } if (ovl->info.enabled) { DSSERR("overlay has to be disabled to change the manager\n"); return -EINVAL; } ovl->manager = mgr; /* do not set channel out if DSS is off */ if (!dss_get_mainclk_state()) return 0; dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); /* XXX: on manual update display, in auto update mode, a bug happens * here. When an overlay is first enabled on LCD, then it's disabled, * and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT * errors. Waiting before changing the channel_out fixes it. I'm * guessing that the overlay is still somehow being used for the LCD, * but I don't understand how or why. */ msleep(40); dispc_set_channel_out(ovl->id, mgr->id); dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); return 0; }
static int dpi_display_resume(struct omap_dss_device *dssdev) { int r = 0; if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) return -EINVAL; DSSDBG("dpi_display_resume\n"); dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL dss_clk_enable(DSS_CLK_FCK2); enable_vpll2_power(1); r = dsi_pll_init(1, 1); if (r) goto err0; r = dpi_set_mode(dssdev); if (r) goto err0; #endif dispc_enable_lcd_out(1); if (dssdev->driver->resume) { r = dssdev->driver->resume(dssdev); if (r) goto err1; } dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; return 0; err1: dispc_enable_lcd_out(0); #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL err0: DSSERR("<%s!!> err0: failed to init DSI_PLL = %d\n", __func__, r); dss_select_clk_source(0, 0); dsi_pll_uninit(); dss_clk_disable(DSS_CLK_FCK2); enable_vpll2_power(0); #endif dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); return r; }
int hdmi_phy_enable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp, struct hdmi_config *cfg) { u16 r = 0; u32 irqstatus; hdmi_wp_clear_irqenable(wp, 0xffffffff); irqstatus = hdmi_wp_get_irqstatus(wp); hdmi_wp_set_irqstatus(wp, irqstatus); r = hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); if (r) return r; /* * Read address 0 in order to get the SCP reset done completed * Dummy access performed to make sure reset is done */ hdmi_read_reg(phy->base, HDMI_TXPHY_TX_CTRL); /* * Write to phy address 0 to configure the clock * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field */ REG_FLD_MOD(phy->base, HDMI_TXPHY_TX_CTRL, 0x1, 31, 30); /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */ hdmi_write_reg(phy->base, HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000); /* Setup max LDO voltage */ REG_FLD_MOD(phy->base, HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0); /* Write to phy address 3 to change the polarity control */ REG_FLD_MOD(phy->base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27); r = request_threaded_irq(phy->irq, NULL, hdmi_irq_handler, IRQF_ONESHOT, "OMAP HDMI", wp); if (r) { DSSERR("HDMI IRQ request failed\n"); hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF); return r; } hdmi_wp_set_irqenable(wp, HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT); return 0; }
static void dispc_mgr_enable_digit_out(void) { DECLARE_COMPLETION_ONSTACK(vsync_compl); int r; u32 irq_mask; if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == true) return; /* * Digit output produces some sync lost interrupts during the first * frame when enabling. Those need to be ignored, so we register for the * sync lost irq to prevent the error handler from triggering. */ irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT) | dispc_mgr_get_sync_lost_irq(OMAP_DSS_CHANNEL_DIGIT); r = omap_dispc_register_isr(dispc_digit_out_enable_isr, &vsync_compl, irq_mask); if (r) { DSSERR("failed to register %x isr\n", irq_mask); return; } dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, true); /* wait for the first evsync */ if (!wait_for_completion_timeout(&vsync_compl, msecs_to_jiffies(100))) DSSERR("timeout waiting for digit out to start\n"); r = omap_dispc_unregister_isr(dispc_digit_out_enable_isr, &vsync_compl, irq_mask); if (r) DSSERR("failed to unregister %x isr\n", irq_mask); }
/* BUS */ static int omap_dss_bus_register(void) { int r; r = bus_register(&dss_bus_type); if (r) { DSSERR("bus register failed\n"); return r; } dev_set_name(&dss_bus, "omapdss"); r = device_register(&dss_bus); if (r) { DSSERR("bus driver register failed\n"); bus_unregister(&dss_bus_type); return r; } core.dss_early_suspend_info.suspend = dss_early_suspend; core.dss_early_suspend_info.resume = dss_late_resume; core.dss_early_suspend_info.level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 1; register_early_suspend(&core.dss_early_suspend_info); return 0; }