Exemplo n.º 1
0
static int
awin_com_match(device_t parent, cfdata_t cf, void *aux)
{
	struct awinio_attach_args * const aio = aux;
	const struct awin_locators * const loc = &aio->aio_loc;
	bus_space_tag_t iot = aio->aio_core_a4x_bst;
	bus_space_handle_t bsh;
	const struct awin_gpio_pinset *pinset;

	if (awin_chip_id() == AWIN_CHIP_ID_A31) {
		pinset = awin_com_pinsets_a31;
	} else if (awin_chip_id() == AWIN_CHIP_ID_A80) {
		pinset = awin_com_pinsets_a80;
	} else {
		pinset = loc->loc_port + ((cf->cf_flags & 1) ?
		    awin_com_alt_pinsets : awin_com_pinsets);
	}

	KASSERT(!strcmp(cf->cf_name, loc->loc_name));
#if defined(ALLWINNER_A80)
	KASSERT(loc->loc_offset >= AWIN_A80_UART0_OFFSET);
	KASSERT(loc->loc_offset <= AWIN_A80_UART5_OFFSET);
#else
	KASSERT(loc->loc_offset >= AWIN_UART0_OFFSET);
	KASSERT(loc->loc_offset <= AWIN_UART7_OFFSET);
#endif
	KASSERT((loc->loc_offset & 0x3ff) == 0);
	KASSERT((awin_com_ports & __BIT(loc->loc_port)) == 0);
	KASSERT(cf->cf_loc[AWINIOCF_PORT] == AWINIOCF_PORT_DEFAULT
	    || cf->cf_loc[AWINIOCF_PORT] == loc->loc_port);

	if (!awin_gpio_pinset_available(pinset))
		return 0;

	if (com_is_console(iot, AWIN_CORE_PBASE + loc->loc_offset, NULL))
		return 1;

	awin_gpio_pinset_acquire(pinset);

	bus_space_subregion(iot, aio->aio_core_bsh,
	    loc->loc_offset, loc->loc_size, &bsh);

	const int rv = comprobe1(iot, bsh);

	awin_gpio_pinset_release(pinset);

	return rv;
}
Exemplo n.º 2
0
static int
awin_gige_match(device_t parent, cfdata_t cf, void *aux)
{
	struct awinio_attach_args * const aio = aux;
#ifdef DIAGNOSTIC
	const struct awin_locators * const loc = &aio->aio_loc;
#endif
	if (cf->cf_flags & 1)
		return 0;

	KASSERT(!strcmp(cf->cf_name, loc->loc_name));
	KASSERT(cf->cf_loc[AWINIOCF_PORT] == AWINIOCF_PORT_DEFAULT
	    || cf->cf_loc[AWINIOCF_PORT] == loc->loc_port);

	if (!awin_gpio_pinset_available(&awin_gige_pinset))
		return 0;

	return 1;
}
Exemplo n.º 3
0
static int
awin_gige_match(device_t parent, cfdata_t cf, void *aux)
{
	const struct awin_gpio_pinset *pinset =
	    awin_chip_id() == AWIN_CHIP_ID_A31 ?
	    &awin_gige_gpio_pinset_a31 : &awin_gige_gpio_pinset;
	struct awinio_attach_args * const aio __diagused = aux;
	const struct awin_locators * const loc __diagused = &aio->aio_loc;
	if (cf->cf_flags & 1)
		return 0;

	KASSERT(!strcmp(cf->cf_name, loc->loc_name));
	KASSERT(cf->cf_loc[AWINIOCF_PORT] == AWINIOCF_PORT_DEFAULT
	    || cf->cf_loc[AWINIOCF_PORT] == loc->loc_port);

	if (!awin_gpio_pinset_available(pinset))
		return 0;

	return 1;
}
Exemplo n.º 4
0
static void
awin_tcon0_set_video(struct awin_tcon_softc *sc)
{
	int32_t lcd_x, lcd_y, lcd_dclk_freq;
	int32_t lcd_hbp, lcd_ht, lcd_vbp, lcd_vt;
	int32_t lcd_hspw, lcd_vspw, lcd_io_cfg0;
	uint32_t vblk, start_delay;
	prop_dictionary_t cfg = device_properties(sc->sc_dev);
	uint32_t val;
	bool propb;
	bool dualchan = false;
	static struct videomode mode;

	if (!prop_dictionary_get_int32(cfg, "lcd_x", &lcd_x)) {
		aprint_error_dev(sc->sc_dev, ": can't read lcd_x\n");
		return;
	}
	if (!prop_dictionary_get_int32(cfg, "lcd_y", &lcd_y)) {
		aprint_error_dev(sc->sc_dev, ": can't read lcd_y\n");
		return;
	}
	if (!prop_dictionary_get_int32(cfg, "lcd_dclk_freq", &lcd_dclk_freq)) {
		aprint_error_dev(sc->sc_dev, ": can't read lcd_dclk_freq\n");
		return;
	}
	if (!prop_dictionary_get_int32(cfg, "lcd_hbp", &lcd_hbp)) {
		aprint_error_dev(sc->sc_dev, ": can't read lcd_hbp\n");
		return;
	}
	if (!prop_dictionary_get_int32(cfg, "lcd_ht", &lcd_ht)) {
		aprint_error_dev(sc->sc_dev, ": can't read lcd_ht\n");
		return;
	}
	if (!prop_dictionary_get_int32(cfg, "lcd_vbp", &lcd_vbp)) {
		aprint_error_dev(sc->sc_dev, ": can't read lcd_vbp\n");
		return;
	}
	if (!prop_dictionary_get_int32(cfg, "lcd_vt", &lcd_vt)) {
		aprint_error_dev(sc->sc_dev, ": can't read lcd_vt\n");
		return;
	}
	if (!prop_dictionary_get_int32(cfg, "lcd_hspw", &lcd_hspw)) {
		aprint_error_dev(sc->sc_dev, ": can't read lcd_hspw\n");
		return;
	}
	if (!prop_dictionary_get_int32(cfg, "lcd_vspw", &lcd_vspw)) {
		aprint_error_dev(sc->sc_dev, ": can't read lcd_vspw\n");
		return;
	}
	if (!prop_dictionary_get_int32(cfg, "lcd_io_cfg0", &lcd_io_cfg0)) {
		aprint_error_dev(sc->sc_dev, ": can't read lcd_io_cfg0\n");
		return;
	}

	if (prop_dictionary_get_bool(cfg, "lvds_dual", &propb) && propb)
		dualchan = true;
	if (!awin_gpio_pinset_available(&awin_lvds0_pinset)) {
		aprint_error_dev(sc->sc_dev, "lvds0 pins not available\n");
		return;
	}
	if (dualchan && !awin_gpio_pinset_available(&awin_lvds1_pinset)) {
		aprint_error_dev(sc->sc_dev, "lvds1 pins not available\n");
		return;
	}
	awin_gpio_pinset_acquire(&awin_lvds0_pinset);
	if (dualchan) {
		awin_gpio_pinset_acquire(&awin_lvds1_pinset);
	}
	prop_dictionary_get_cstring_nocopy(cfg, "lcd_power_en",
	    &sc->sc_lcdpwr_pin_name);
	if (sc->sc_lcdpwr_pin_name != NULL) {
		if (!awin_gpio_pin_reserve(
		    sc->sc_lcdpwr_pin_name, &sc->sc_lcdpwr_pin)) {
			aprint_error_dev(sc->sc_dev,
			    "failed to reserve GPIO \"%s\" for LCD power\n",
			    sc->sc_lcdpwr_pin_name);
			sc->sc_lcdpwr_pin_name = NULL;
		} else {
			aprint_verbose_dev(sc->sc_dev,
			    ": using GPIO \"%s\" for LCD power\n", 
			    sc->sc_lcdpwr_pin_name);
		}
	}
	prop_dictionary_get_cstring_nocopy(cfg, "lcd_bl_en",
	    &sc->sc_lcdblk_pin_name);
	if (sc->sc_lcdblk_pin_name != NULL) {
		if (!awin_gpio_pin_reserve(
		    sc->sc_lcdblk_pin_name, &sc->sc_lcdblk_pin)) {
			aprint_error_dev(sc->sc_dev,
			    "failed to reserve GPIO \"%s\" for backlight\n",
			    sc->sc_lcdblk_pin_name);
			sc->sc_lcdblk_pin_name = NULL;
		} else {
			if (sc->sc_lcdpwr_pin_name == NULL) {
				aprint_verbose_dev(sc->sc_dev,
				    ": using GPIO \"%s\" for backlight\n", 
				    sc->sc_lcdblk_pin_name);
			} else {
				aprint_verbose(
				    ", GPIO \"%s\" for backlight\n", 
				    sc->sc_lcdblk_pin_name);
			}
		}
	}

	if (sc->sc_lcdpwr_pin_name != NULL) {
		awin_gpio_pindata_write(&sc->sc_lcdpwr_pin, 1);
	}

	vblk = (lcd_vt / 2) - lcd_y;
	start_delay = (vblk >= 32) ? 30 : (vblk - 2);

	if (lcd_dclk_freq > 150) /* hardware limit ? */
		lcd_dclk_freq = 150;
	awin_tcon_set_pll(sc, lcd_dclk_freq * 1000, 7);

	val = AWIN_TCONx_CTL_EN;
	val |= __SHIFTIN(start_delay, AWIN_TCONx_CTL_START_DELAY);
	/*
	 * the DE selector selects the primary DEBE for this tcon:
	 * 0 selects debe0 for tcon0 and debe1 for tcon1
	 */
	val |= __SHIFTIN(AWIN_TCONx_CTL_SRC_SEL_DE0,
			 AWIN_TCONx_CTL_SRC_SEL);
	TCON_WRITE(sc, AWIN_TCON0_CTL_REG, val);

	val =  (lcd_x - 1) << 16 |  (lcd_y - 1);
	TCON_WRITE(sc, AWIN_TCON0_BASIC0_REG, val);
	val = (lcd_ht - 1) << 16 | (lcd_hbp - 1);
	TCON_WRITE(sc, AWIN_TCON0_BASIC1_REG, val);
	val = (lcd_vt) << 16 | (lcd_vbp - 1);
	TCON_WRITE(sc, AWIN_TCON0_BASIC2_REG, val);
	val =  ((lcd_hspw > 0) ? (lcd_hspw - 1) : 0) << 16;
	val |= ((lcd_vspw > 0) ? (lcd_vspw - 1) : 0);
	TCON_WRITE(sc, AWIN_TCON0_BASIC3_REG, val);

	val = 0;
	if (dualchan)
		val |= AWIN_TCON0_LVDS_IF_DUALCHAN;
	if (prop_dictionary_get_bool(cfg, "lvds_mode_jeida", &propb) && propb)
		val |= AWIN_TCON0_LVDS_IF_MODE_JEIDA;
	if (prop_dictionary_get_bool(cfg, "lvds_18bits", &propb) && propb)
		val |= AWIN_TCON0_LVDS_IF_18BITS;
	TCON_WRITE(sc, AWIN_TCON0_LVDS_IF_REG, val);


	TCON_WRITE(sc, AWIN_TCON0_IO_POL_REG, lcd_io_cfg0);
	TCON_WRITE(sc, AWIN_TCON0_IO_TRI_REG, 0);
	TCON_WRITE(sc, AWIN_TCON_GINT1_REG,
	    __SHIFTIN(start_delay + 2, AWIN_TCON_GINT1_TCON0_LINENO));

	val = 0xf0000000;
	val &= ~AWIN_TCON0_DCLK_DIV;
	val |= __SHIFTIN(sc->sc_clk_div, AWIN_TCON0_DCLK_DIV);
	TCON_WRITE(sc, AWIN_TCON0_DCLK_REG, val);

	mode.dot_clock = lcd_dclk_freq;
	mode.hdisplay = lcd_x;
	mode.hsync_start = lcd_ht - lcd_hbp;
	mode.hsync_end = lcd_hspw + mode.hsync_start;
	mode.htotal = lcd_ht;
	mode.vdisplay = lcd_y;
	mode.vsync_start = lcd_vt - lcd_vbp;
	mode.vsync_end = lcd_vspw + mode.vsync_start;
	mode.vtotal = lcd_vt;
	mode.flags = 0;
	mode.name = NULL;

	awin_debe_set_videomode(sc->sc_debe_unit, &mode);

	/* and finally, enable it */
	awin_debe_enable(sc->sc_debe_unit, true);
	delay(20000);

	val = TCON_READ(sc, AWIN_TCON_GCTL_REG);
	val |= AWIN_TCON_GCTL_EN;
	TCON_WRITE(sc, AWIN_TCON_GCTL_REG, val);
	delay(20000);


	val = TCON_READ(sc, AWIN_TCON0_LVDS_IF_REG);
	val |= AWIN_TCON0_LVDS_IF_EN;
	TCON_WRITE(sc, AWIN_TCON0_LVDS_IF_REG, val);

	/* XXX
	 * magic values here from linux. these are not documented
	 * in the A20 user manual, and other Allwiner LVDS-capable SoC
	 * documentation don't make sense with these values
	 */
	val = TCON_READ(sc, AWIN_TCON_LVDS_ANA0);
	val |= 0x3F310000;
	TCON_WRITE(sc, AWIN_TCON_LVDS_ANA0, val);
	val = TCON_READ(sc, AWIN_TCON_LVDS_ANA0);
	val |= 1 << 22;
	TCON_WRITE(sc, AWIN_TCON_LVDS_ANA0, val);
	delay(2);
	val = TCON_READ(sc, AWIN_TCON_LVDS_ANA1);
	val |= (0x1f << 26 | 0x1f << 10);
	TCON_WRITE(sc, AWIN_TCON_LVDS_ANA1, val);
	delay(2);
	val = TCON_READ(sc, AWIN_TCON_LVDS_ANA1);
	val |= (0x1f << 16 | 0x1f << 0);
	TCON_WRITE(sc, AWIN_TCON_LVDS_ANA1, val);
	val = TCON_READ(sc, AWIN_TCON_LVDS_ANA0);
	val |= 1 << 22;
	TCON_WRITE(sc, AWIN_TCON_LVDS_ANA0, val);

	if (sc->sc_lcdblk_pin_name != NULL) {
		awin_gpio_pindata_write(&sc->sc_lcdblk_pin, 1);
	}
}