Esempio n. 1
0
static int
am335x_lcd_attach(device_t dev)
{
    struct am335x_lcd_softc *sc;
    int rid;
    int div;
    struct panel_info panel;
    uint32_t reg, timing0, timing1, timing2;
    struct sysctl_ctx_list *ctx;
    struct sysctl_oid *tree;
    uint32_t burst_log;
    int err;
    size_t dma_size;

    sc = device_get_softc(dev);
    sc->sc_dev = dev;

    if (am335x_read_panel_info(dev, &panel))
        return (ENXIO);

    int ref_freq = 0;
    ti_prcm_clk_enable(LCDC_CLK);
    if (ti_prcm_clk_get_source_freq(LCDC_CLK, &ref_freq)) {
        device_printf(dev, "Can't get reference frequency\n");
        return (ENXIO);
    }

    rid = 0;
    sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
                                            RF_ACTIVE);
    if (!sc->sc_mem_res) {
        device_printf(dev, "cannot allocate memory window\n");
        return (ENXIO);
    }

    rid = 0;
    sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
                                            RF_ACTIVE);
    if (!sc->sc_irq_res) {
        bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
        device_printf(dev, "cannot allocate interrupt\n");
        return (ENXIO);
    }

    if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
                       NULL, am335x_lcd_intr, sc,
                       &sc->sc_intr_hl) != 0) {
        bus_release_resource(dev, SYS_RES_IRQ, rid,
                             sc->sc_irq_res);
        bus_release_resource(dev, SYS_RES_MEMORY, rid,
                             sc->sc_mem_res);
        device_printf(dev, "Unable to setup the irq handler.\n");
        return (ENXIO);
    }

    LCD_LOCK_INIT(sc);

    /* Panle initialization */
    dma_size = round_page(panel.panel_width*panel.panel_height*panel.bpp/8);

    /*
     * Now allocate framebuffer memory
     */
    err = bus_dma_tag_create(
              bus_get_dma_tag(dev),
              4, 0,		/* alignment, boundary */
              BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
              BUS_SPACE_MAXADDR,		/* highaddr */
              NULL, NULL,			/* filter, filterarg */
              dma_size, 1,			/* maxsize, nsegments */
              dma_size, 0,			/* maxsegsize, flags */
              NULL, NULL,			/* lockfunc, lockarg */
              &sc->sc_dma_tag);
    if (err)
        goto fail;

    err = bus_dmamem_alloc(sc->sc_dma_tag, (void **)&sc->sc_fb_base,
                           BUS_DMA_COHERENT, &sc->sc_dma_map);

    if (err) {
        device_printf(dev, "cannot allocate framebuffer\n");
        goto fail;
    }

    err = bus_dmamap_load(sc->sc_dma_tag, sc->sc_dma_map, sc->sc_fb_base,
                          dma_size, am335x_fb_dmamap_cb, &sc->sc_fb_phys, BUS_DMA_NOWAIT);

    if (err) {
        device_printf(dev, "cannot load DMA map\n");
        goto fail;
    }

    /* Make sure it's blank */
    memset(sc->sc_fb_base, 0x00, dma_size);

    /* Calculate actual FB Size */
    sc->sc_fb_size = panel.panel_width*panel.panel_height*panel.bpp/8;

    /* Only raster mode is supported */
    reg = CTRL_RASTER_MODE;
    div = am335x_lcd_calc_divisor(ref_freq, panel.panel_pxl_clk);
    reg |= (div << CTRL_DIV_SHIFT);
    LCD_WRITE4(sc, LCD_CTRL, reg);

    /* Set timing */
    timing0 = timing1 = timing2 = 0;

    /* Horizontal back porch */
    timing0 |= (panel.panel_hbp & 0xff) << RASTER_TIMING_0_HBP_SHIFT;
    timing2 |= ((panel.panel_hbp >> 8) & 3) << RASTER_TIMING_2_HBPHI_SHIFT;
    /* Horizontal front porch */
    timing0 |= (panel.panel_hfp & 0xff) << RASTER_TIMING_0_HFP_SHIFT;
    timing2 |= ((panel.panel_hfp >> 8) & 3) << RASTER_TIMING_2_HFPHI_SHIFT;
    /* Horizontal sync width */
    timing0 |= (panel.panel_hsw & 0x3f) << RASTER_TIMING_0_HSW_SHIFT;
    timing2 |= ((panel.panel_hsw >> 6) & 0xf) << RASTER_TIMING_2_HSWHI_SHIFT;

    /* Vertical back porch, front porch, sync width */
    timing1 |= (panel.panel_vbp & 0xff) << RASTER_TIMING_1_VBP_SHIFT;
    timing1 |= (panel.panel_vfp & 0xff) << RASTER_TIMING_1_VFP_SHIFT;
    timing1 |= (panel.panel_vsw & 0x3f) << RASTER_TIMING_1_VSW_SHIFT;

    /* Pixels per line */
    timing0 |= (((panel.panel_width - 1) >> 10) & 1)
               << RASTER_TIMING_0_PPLMSB_SHIFT;
    timing0 |= (((panel.panel_width - 1) >> 4) & 0x3f)
               << RASTER_TIMING_0_PPLLSB_SHIFT;

    /* Lines per panel */
    timing1 |= ((panel.panel_height - 1) & 0x3ff)
               << RASTER_TIMING_1_LPP_SHIFT;
    timing2 |= (((panel.panel_height - 1) >> 10 ) & 1)
               << RASTER_TIMING_2_LPP_B10_SHIFT;

    /* clock signal settings */
    if (panel.sync_ctrl)
        timing2 |= RASTER_TIMING_2_PHSVS;
    if (panel.sync_edge)
        timing2 |= RASTER_TIMING_2_PHSVS_RISE;
    else
        timing2 |= RASTER_TIMING_2_PHSVS_FALL;
    if (panel.invert_line_clock)
        timing2 |= RASTER_TIMING_2_IHS;
    if (panel.invert_frm_clock)
        timing2 |= RASTER_TIMING_2_IVS;
    if (panel.panel_invert_pxl_clk)
        timing2 |= RASTER_TIMING_2_IPC;

    /* AC bias */
    timing2 |= (panel.ac_bias << RASTER_TIMING_2_ACB_SHIFT);
    timing2 |= (panel.ac_bias_intrpt << RASTER_TIMING_2_ACBI_SHIFT);

    LCD_WRITE4(sc, LCD_RASTER_TIMING_0, timing0);
    LCD_WRITE4(sc, LCD_RASTER_TIMING_1, timing1);
    LCD_WRITE4(sc, LCD_RASTER_TIMING_2, timing2);

    /* DMA settings */
    reg = LCDDMA_CTRL_FB0_FB1;
    /* Find power of 2 for current burst size */
    switch (panel.dma_burst_sz) {
    case 1:
        burst_log = 0;
        break;
    case 2:
        burst_log = 1;
        break;
    case 4:
        burst_log = 2;
        break;
    case 8:
        burst_log = 3;
        break;
    case 16:
    default:
        burst_log = 4;
        break;
    }
    reg |= (burst_log << LCDDMA_CTRL_BURST_SIZE_SHIFT);
    /* XXX: FIFO TH */
    reg |= (0 << LCDDMA_CTRL_TH_FIFO_RDY_SHIFT);
    LCD_WRITE4(sc, LCD_LCDDMA_CTRL, reg);

    LCD_WRITE4(sc, LCD_LCDDMA_FB0_BASE, sc->sc_fb_phys);
    LCD_WRITE4(sc, LCD_LCDDMA_FB0_CEILING, sc->sc_fb_phys + sc->sc_fb_size - 1);
    LCD_WRITE4(sc, LCD_LCDDMA_FB1_BASE, sc->sc_fb_phys);
    LCD_WRITE4(sc, LCD_LCDDMA_FB1_CEILING, sc->sc_fb_phys + sc->sc_fb_size - 1);

    /* Enable LCD */
    reg = RASTER_CTRL_LCDTFT;
    reg |= (panel.fdd << RASTER_CTRL_REQDLY_SHIFT);
    reg |= (PALETTE_DATA_ONLY << RASTER_CTRL_PALMODE_SHIFT);
    if (panel.bpp >= 24)
        reg |= RASTER_CTRL_TFT24;
    if (panel.bpp == 32)
        reg |= RASTER_CTRL_TFT24_UNPACKED;
    LCD_WRITE4(sc, LCD_RASTER_CTRL, reg);

    LCD_WRITE4(sc, LCD_CLKC_ENABLE,
               CLKC_ENABLE_DMA | CLKC_ENABLE_LDID | CLKC_ENABLE_CORE);

    LCD_WRITE4(sc, LCD_CLKC_RESET, CLKC_RESET_MAIN);
    DELAY(100);
    LCD_WRITE4(sc, LCD_CLKC_RESET, 0);

    reg = IRQ_EOF1 | IRQ_EOF0 | IRQ_FUF | IRQ_PL |
          IRQ_ACB | IRQ_SYNC_LOST |  IRQ_RASTER_DONE |
          IRQ_FRAME_DONE;
    LCD_WRITE4(sc, LCD_IRQENABLE_SET, reg);

    reg = LCD_READ4(sc, LCD_RASTER_CTRL);
    reg |= RASTER_CTRL_LCDEN;
    LCD_WRITE4(sc, LCD_RASTER_CTRL, reg);

    LCD_WRITE4(sc, LCD_SYSCONFIG,
               SYSCONFIG_STANDBY_SMART | SYSCONFIG_IDLE_SMART);

    /* Init backlight interface */
    ctx = device_get_sysctl_ctx(sc->sc_dev);
    tree = device_get_sysctl_tree(sc->sc_dev);
    sc->sc_oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
                                 "backlight", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
                                 am335x_lcd_sysctl_backlight, "I", "LCD backlight");
    sc->sc_backlight = 0;
    /* Check if eCAS interface is available at this point */
    if (am335x_pwm_config_ecas(PWM_UNIT,
                               PWM_PERIOD, PWM_PERIOD) == 0)
        sc->sc_backlight = 100;

    err = (sc_attach_unit(device_get_unit(dev),
                          device_get_flags(dev) | SC_AUTODETECT_KBD));

    if (err) {
        device_printf(dev, "failed to attach syscons\n");
        goto fail;
    }

    am335x_lcd_syscons_setup((vm_offset_t)sc->sc_fb_base, sc->sc_fb_phys, &panel);

    return (0);

fail:
    return (err);
}
Esempio n. 2
0
/**
 *	ti_mmchs_hw_init - initialises the MMC/SD/SIO controller
 *	@dev: mmc device handle
 *
 *	Called by the driver attach function during driver initialisation. This
 *	function is responsibly to setup the controller ready for transactions.
 *
 *	LOCKING:
 *	No locking, assumed to only be called during initialisation.
 *
 *	RETURNS:
 *	nothing
 */
static void
ti_mmchs_hw_init(device_t dev)
{
	struct ti_mmchs_softc *sc = device_get_softc(dev);
	clk_ident_t clk;
	unsigned long timeout;
	uint32_t sysctl;
	uint32_t capa;
	uint32_t con;

	/* 1: Enable the controller and interface/functional clocks */
	clk = MMC1_CLK + device_get_unit(dev);

	if (ti_prcm_clk_enable(clk) != 0) {
		device_printf(dev, "Error: failed to enable MMC clock\n");
		return;
	}

	/* 1a: Get the frequency of the source clock */
	if (ti_prcm_clk_get_source_freq(clk, &sc->sc_ref_freq) != 0) {
		device_printf(dev, "Error: failed to get source clock freq\n");
		return;
	}

	/* 2: Issue a softreset to the controller */
	ti_mmchs_write_4(sc, MMCHS_SYSCONFIG, 0x0002);
	timeout = 100;
	while ((ti_mmchs_read_4(sc, MMCHS_SYSSTATUS) & 0x01) == 0x0) {
		DELAY(1000);
		if (timeout-- == 0) {
			device_printf(dev, "Error: reset operation timed out\n");
			return;
		}
	}

	/* 3: Reset both the command and data state machines */
	sysctl = ti_mmchs_read_4(sc, MMCHS_SYSCTL);
	ti_mmchs_write_4(sc, MMCHS_SYSCTL, sysctl | MMCHS_SYSCTL_SRA);
	timeout = 100;
	while ((ti_mmchs_read_4(sc, MMCHS_SYSCTL) & MMCHS_SYSCTL_SRA) != 0x0) {
		DELAY(1000);
		if (timeout-- == 0) {
			device_printf(dev, "Error: reset operation timed out\n");
			return;
		}
	}

	/* 4: Set initial host configuration (1-bit mode, pwroff) and capabilities */
	ti_mmchs_write_4(sc, MMCHS_HCTL, MMCHS_HCTL_SDVS_V30);

	capa = ti_mmchs_read_4(sc, MMCHS_CAPA);
	ti_mmchs_write_4(sc, MMCHS_CAPA, capa | MMCHS_CAPA_VS30 | MMCHS_CAPA_VS18);

	/* 5: Set the initial bus configuration
	 *       0  CTPL_MMC_SD      : Control Power for DAT1 line
	 *       0  WPP_ACTIVE_HIGH  : Write protect polarity
	 *       0  CDP_ACTIVE_HIGH  : Card detect polarity
	 *       0  CTO_ENABLED      : MMC interrupt command
	 *       0  DW8_DISABLED     : 8-bit mode MMC select
	 *       0  MODE_FUNC        : Mode select
	 *       0  STREAM_DISABLED  : Stream command
	 *       0  HR_DISABLED      : Broadcast host response
	 *       0  INIT_DISABLED    : Send initialization stream
	 *       0  OD_DISABLED      : No Open Drain
	 */
	con = ti_mmchs_read_4(sc, MMCHS_CON) & MMCHS_CON_DVAL_MASK;
	ti_mmchs_write_4(sc, MMCHS_CON, con);

}