Esempio n. 1
0
static void
am335x_lcd_intr(void *arg)
{
	struct am335x_lcd_softc *sc = arg;
	uint32_t reg; 

	reg = LCD_READ4(sc, LCD_IRQSTATUS);
	LCD_WRITE4(sc, LCD_IRQSTATUS, reg);
	/* Read value back to make sure it reached the hardware */
	reg = LCD_READ4(sc, LCD_IRQSTATUS);

	if (reg & IRQ_SYNC_LOST) {
		reg = LCD_READ4(sc, LCD_RASTER_CTRL);
		reg &= ~RASTER_CTRL_LCDEN;
		LCD_WRITE4(sc, LCD_RASTER_CTRL, reg); 

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

	if (reg & IRQ_PL) {
		reg = LCD_READ4(sc, LCD_RASTER_CTRL);
		reg &= ~RASTER_CTRL_LCDEN;
		LCD_WRITE4(sc, LCD_RASTER_CTRL, reg); 

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

	if (reg & IRQ_EOF0) {
		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); 
		reg &= ~IRQ_EOF0;
	}

	if (reg & IRQ_EOF1) {
		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); 
		reg &= ~IRQ_EOF1;
	}

	if (reg & IRQ_FUF) {
		/* TODO: Handle FUF */
	}

	if (reg & IRQ_ACB) {
		/* TODO: Handle ACB */
	}

done:
	LCD_WRITE4(sc, LCD_END_OF_INT_IND, 0);
	/* Read value back to make sure it reached the hardware */
	reg = LCD_READ4(sc, LCD_END_OF_INT_IND);
}
Esempio n. 2
0
static void
am335x_lcd_intr(void *arg)
{
    struct am335x_lcd_softc *sc = arg;
    uint32_t reg;

    reg = LCD_READ4(sc, LCD_IRQSTATUS);
    LCD_WRITE4(sc, LCD_IRQSTATUS, reg);

    if (reg & IRQ_SYNC_LOST) {
        reg = LCD_READ4(sc, LCD_RASTER_CTRL);
        reg &= ~RASTER_CTRL_LCDEN;
        LCD_WRITE4(sc, LCD_RASTER_CTRL, reg);

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

    if (reg & IRQ_PL) {
        reg = LCD_READ4(sc, LCD_RASTER_CTRL);
        reg &= ~RASTER_CTRL_LCDEN;
        LCD_WRITE4(sc, LCD_RASTER_CTRL, reg);

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

    if (reg & IRQ_EOF0) {
        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);
        reg &= ~IRQ_EOF0;
    }

    if (reg & IRQ_EOF1) {
        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);
        reg &= ~IRQ_EOF1;
    }

    if (reg & IRQ_FUF) {
        /* TODO: Handle FUF */
    }

    if (reg & IRQ_ACB) {
        /* TODO: Handle ACB */
    }
}
Esempio n. 3
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);
}