static void awin_tve_attach(device_t parent, device_t self, void *aux) { struct awin_tve_softc *sc = device_private(self); struct awinio_attach_args * const aio = aux; const struct awin_locators * const loc = &aio->aio_loc; prop_dictionary_t cfg = device_properties(self); int8_t tcon_unit = -1; sc->sc_dev = self; sc->sc_bst = aio->aio_core_bst; bus_space_subregion(sc->sc_bst, aio->aio_core_bsh, loc->loc_offset, loc->loc_size, &sc->sc_bsh); if (prop_dictionary_get_int8(cfg, "tcon_unit", &tcon_unit)) { sc->sc_tcon_unit = tcon_unit; } else { sc->sc_tcon_unit = 0; /* default value */ } sc->sc_tcon_pll = awin_tcon_get_clk_pll(sc->sc_tcon_unit); switch (sc->sc_tcon_pll) { case 3: awin_pll3_enable(); break; case 7: awin_pll7_enable(); break; default: panic("awin_tve pll"); } /* for now assume we're always at 0 */ awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, AWIN_AHB_GATING1_REG, AWIN_AHB_GATING1_TVE0, 0); aprint_naive("\n"); aprint_normal(": TV Encoder / VGA output\n"); if (tcon_unit >= 0) { aprint_verbose_dev(self, ": using TCON%d, pll%d\n", sc->sc_tcon_unit, sc->sc_tcon_pll); } sc->sc_i2c_blklen = 16; #if 0 sc->sc_ih = intr_establish(loc->loc_intr, IPL_SCHED, IST_LEVEL, awin_tve_intr, sc); if (sc->sc_ih == NULL) { aprint_error_dev(self, "couldn't establish interrupt %d\n", loc->loc_intr); return; } aprint_normal_dev(self, "interrupting on irq %d\n", loc->loc_intr); #endif awin_tve_i2c_init(sc); awin_tve_enable(sc); awin_tve_read_edid(sc); }
static void awin_hdmi_attach(device_t parent, device_t self, void *aux) { struct awin_hdmi_softc *sc = device_private(self); struct awinio_attach_args * const aio = aux; const struct awin_locators * const loc = &aio->aio_loc; prop_dictionary_t cfg = device_properties(self); uint32_t ver, clk; sc->sc_dev = self; sc->sc_bst = aio->aio_core_bst; bus_space_subregion(sc->sc_bst, aio->aio_core_bsh, loc->loc_offset, loc->loc_size, &sc->sc_bsh); #if AWIN_HDMI_PLL == 3 awin_pll3_enable(); #elif AWIN_HDMI_PLL == 7 awin_pll7_enable(); #else #error AWIN_HDMI_PLL must be 3 or 7 #endif if (awin_chip_id() == AWIN_CHIP_ID_A31) { awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, AWIN_A31_AHB_RESET1_REG, AWIN_A31_AHB_RESET1_HDMI_RST, 0); } #if AWIN_HDMI_PLL == 3 clk = __SHIFTIN(AWIN_HDMI_CLK_SRC_SEL_PLL3, AWIN_HDMI_CLK_SRC_SEL); #else clk = __SHIFTIN(AWIN_HDMI_CLK_SRC_SEL_PLL7, AWIN_HDMI_CLK_SRC_SEL); #endif clk |= AWIN_CLK_ENABLE; if (awin_chip_id() == AWIN_CHIP_ID_A31) { clk |= AWIN_A31_HDMI_CLK_DDC_GATING; } awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, AWIN_HDMI_CLK_REG, clk, AWIN_HDMI_CLK_SRC_SEL); awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, AWIN_AHB_GATING1_REG, AWIN_AHB_GATING1_HDMI, 0); ver = HDMI_READ(sc, AWIN_HDMI_VERSION_ID_REG); const int vmaj = __SHIFTOUT(ver, AWIN_HDMI_VERSION_ID_H); const int vmin = __SHIFTOUT(ver, AWIN_HDMI_VERSION_ID_L); aprint_naive("\n"); aprint_normal(": HDMI %d.%d\n", vmaj, vmin); sc->sc_ver = ver; sc->sc_i2c_blklen = 16; const char *display_mode = NULL; prop_dictionary_get_cstring_nocopy(cfg, "display-mode", &display_mode); if (display_mode) { if (strcasecmp(display_mode, "hdmi") == 0) sc->sc_display_mode = DISPLAY_MODE_HDMI; else if (strcasecmp(display_mode, "dvi") == 0) sc->sc_display_mode = DISPLAY_MODE_DVI; } #if 0 sc->sc_ih = intr_establish(loc->loc_intr, IPL_SCHED, IST_LEVEL, awin_hdmi_intr, sc); if (sc->sc_ih == NULL) { aprint_error_dev(self, "couldn't establish interrupt %d\n", loc->loc_intr); return; } aprint_normal_dev(self, "interrupting on irq %d\n", loc->loc_intr); #endif awin_hdmi_i2c_init(sc); awin_hdmi_enable(sc); delay(50000); awin_hdmi_hpd(sc); kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, awin_hdmi_thread, sc, &sc->sc_thread, "%s", device_xname(sc->sc_dev)); }
static void awin_tcon_attach(device_t parent, device_t self, void *aux) { struct awin_tcon_softc *sc = device_private(self); struct awinio_attach_args * const aio = aux; const struct awin_locators * const loc = &aio->aio_loc; prop_dictionary_t cfg = device_properties(self); const char *output; sc->sc_dev = self; sc->sc_bst = aio->aio_core_bst; sc->sc_port = loc->loc_port; bus_space_subregion(sc->sc_bst, aio->aio_core_bsh, loc->loc_offset, loc->loc_size, &sc->sc_bsh); bus_space_subregion(sc->sc_bst, aio->aio_ccm_bsh, AWIN_LCD0_CH0_CLK_REG + (loc->loc_port * 4), 4, &sc->sc_ch0clk_bsh); bus_space_subregion(sc->sc_bst, aio->aio_ccm_bsh, AWIN_LCD0_CH1_CLK_REG + (loc->loc_port * 4), 4, &sc->sc_ch1clk_bsh); if (!tcon_mux_inited) { /* the mux register is only in LCD0 */ bus_space_subregion(sc->sc_bst, aio->aio_core_bsh, AWIN_LCD0_OFFSET + AWIN_TCON_MUX_CTL_REG, 4, &tcon_mux_bsh); tcon_mux_inited = true; /* always enable tcon0, the mux is there */ awin_tcon_clear_reset(aio, 0); } if (prop_dictionary_get_cstring_nocopy(cfg, "output", &output)) { if (strcmp(output, "hdmi") == 0) { sc->sc_output_type = OUTPUT_HDMI; } else if (strcmp(output, "lvds") == 0) { sc->sc_output_type = OUTPUT_LVDS; } else if (strcmp(output, "vga") == 0) { sc->sc_output_type = OUTPUT_VGA; } else { panic("tcon: wrong mode %s", output); } } else { sc->sc_output_type = OUTPUT_HDMI; /* default */ } aprint_naive("\n"); aprint_normal(": LCD/TV timing controller (TCON%d)\n", loc->loc_port); switch (sc->sc_port) { case 0: awin_pll3_enable(); sc->sc_clk_pll = 3; break; case 1: awin_pll7_enable(); sc->sc_clk_pll = 7; break; default: panic("awin_tcon port\n"); } aprint_verbose_dev(self, ": using DEBE%d, pll%d\n", device_unit(self), sc->sc_clk_pll); awin_tcon_clear_reset(aio, sc->sc_port); TCON_WRITE(sc, AWIN_TCON_GCTL_REG, 0); TCON_WRITE(sc, AWIN_TCON_GINT0_REG, 0); TCON_WRITE(sc, AWIN_TCON_GINT1_REG, __SHIFTIN(0x20, AWIN_TCON_GINT1_TCON0_LINENO)); TCON_WRITE(sc, AWIN_TCON0_DCLK_REG, 0xf0000000); TCON_WRITE(sc, AWIN_TCON0_CTL_REG, 0); TCON_WRITE(sc, AWIN_TCON0_IO_TRI_REG, 0xffffffff); TCON_WRITE(sc, AWIN_TCON1_CTL_REG, 0); TCON_WRITE(sc, AWIN_TCON1_IO_TRI_REG, 0xffffffff); if (sc->sc_output_type == OUTPUT_LVDS) { awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, AWIN_LVDS_CLK_REG, AWIN_LVDS_CLK_ENABLE, 0); awin_tcon0_set_video(sc); } }