Changeset View
Changeset View
Standalone View
Standalone View
head/sys/arm/ti/am335x/am335x_lcd.c
Show First 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | |||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <vm/vm.h> | #include <vm/vm.h> | ||||
#include <vm/pmap.h> | #include <vm/pmap.h> | ||||
#include <sys/fbio.h> | #include <sys/fbio.h> | ||||
#include <sys/consio.h> | #include <sys/consio.h> | ||||
#include <machine/bus.h> | #include <machine/bus.h> | ||||
#include <dev/extres/clk/clk.h> | |||||
#include <dev/fdt/fdt_common.h> | #include <dev/fdt/fdt_common.h> | ||||
#include <dev/ofw/openfirm.h> | #include <dev/ofw/openfirm.h> | ||||
#include <dev/ofw/ofw_bus.h> | #include <dev/ofw/ofw_bus.h> | ||||
#include <dev/ofw/ofw_bus_subr.h> | #include <dev/ofw/ofw_bus_subr.h> | ||||
#include <dev/videomode/videomode.h> | #include <dev/videomode/videomode.h> | ||||
#include <dev/videomode/edidvar.h> | #include <dev/videomode/edidvar.h> | ||||
#include <dev/fb/fbreg.h> | #include <dev/fb/fbreg.h> | ||||
#ifdef DEV_SC | #ifdef DEV_SC | ||||
#include <dev/syscons/syscons.h> | #include <dev/syscons/syscons.h> | ||||
#else /* VT */ | #else /* VT */ | ||||
#include <dev/vt/vt.h> | #include <dev/vt/vt.h> | ||||
#endif | #endif | ||||
#include <arm/ti/ti_prcm.h> | #include <arm/ti/ti_sysc.h> | ||||
#include <arm/ti/ti_scm.h> | #include <arm/ti/ti_scm.h> | ||||
#include "am335x_lcd.h" | #include "am335x_lcd.h" | ||||
#include "am335x_pwm.h" | #include "am335x_pwm.h" | ||||
#include "fb_if.h" | #include "fb_if.h" | ||||
#include "hdmi_if.h" | #include "hdmi_if.h" | ||||
▲ Show 20 Lines • Show All 137 Lines • ▼ Show 20 Lines | struct am335x_lcd_softc { | ||||
bus_dmamap_t sc_dma_map; | bus_dmamap_t sc_dma_map; | ||||
size_t sc_fb_size; | size_t sc_fb_size; | ||||
bus_addr_t sc_fb_phys; | bus_addr_t sc_fb_phys; | ||||
uint8_t *sc_fb_base; | uint8_t *sc_fb_base; | ||||
/* HDMI framer */ | /* HDMI framer */ | ||||
phandle_t sc_hdmi_framer; | phandle_t sc_hdmi_framer; | ||||
eventhandler_tag sc_hdmi_evh; | eventhandler_tag sc_hdmi_evh; | ||||
/* Clock */ | |||||
clk_t sc_clk_dpll_disp_ck; | |||||
}; | }; | ||||
static void | static void | ||||
am335x_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err) | am335x_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err) | ||||
{ | { | ||||
bus_addr_t *addr; | bus_addr_t *addr; | ||||
if (err) | if (err) | ||||
▲ Show 20 Lines • Show All 380 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
int div; | int div; | ||||
uint32_t reg, timing0, timing1, timing2; | uint32_t reg, timing0, timing1, timing2; | ||||
uint32_t burst_log; | uint32_t burst_log; | ||||
size_t dma_size; | size_t dma_size; | ||||
uint32_t hbp, hfp, hsw; | uint32_t hbp, hfp, hsw; | ||||
uint32_t vbp, vfp, vsw; | uint32_t vbp, vfp, vsw; | ||||
uint32_t width, height; | uint32_t width, height; | ||||
unsigned int ref_freq; | uint64_t ref_freq; | ||||
int err; | int err; | ||||
/* | /* | ||||
* try to adjust clock to get double of requested frequency | * try to adjust clock to get double of requested frequency | ||||
* HDMI/DVI displays are very sensitive to error in frequncy value | * HDMI/DVI displays are very sensitive to error in frequncy value | ||||
*/ | */ | ||||
if (ti_prcm_clk_set_source_freq(LCDC_CLK, sc->sc_panel.panel_pxl_clk*2)) { | |||||
err = clk_set_freq(sc->sc_clk_dpll_disp_ck, sc->sc_panel.panel_pxl_clk*2, | |||||
CLK_SET_ROUND_ANY); | |||||
if (err != 0) { | |||||
device_printf(sc->sc_dev, "can't set source frequency\n"); | device_printf(sc->sc_dev, "can't set source frequency\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
if (ti_prcm_clk_get_source_freq(LCDC_CLK, &ref_freq)) { | err = clk_get_freq(sc->sc_clk_dpll_disp_ck, &ref_freq); | ||||
if (err != 0) { | |||||
device_printf(sc->sc_dev, "can't get reference frequency\n"); | device_printf(sc->sc_dev, "can't get reference frequency\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
/* Panle initialization */ | /* Panel initialization */ | ||||
dma_size = round_page(sc->sc_panel.panel_width*sc->sc_panel.panel_height*sc->sc_panel.bpp/8); | dma_size = round_page(sc->sc_panel.panel_width*sc->sc_panel.panel_height*sc->sc_panel.bpp/8); | ||||
/* | /* | ||||
* Now allocate framebuffer memory | * Now allocate framebuffer memory | ||||
*/ | */ | ||||
err = bus_dma_tag_create( | err = bus_dma_tag_create( | ||||
bus_get_dma_tag(sc->sc_dev), | bus_get_dma_tag(sc->sc_dev), | ||||
4, 0, /* alignment, boundary */ | 4, 0, /* alignment, boundary */ | ||||
▲ Show 20 Lines • Show All 318 Lines • ▼ Show 20 Lines | am335x_lcd_attach(device_t dev) | ||||
am335x_read_hdmi_property(dev); | am335x_read_hdmi_property(dev); | ||||
root = OF_finddevice("/"); | root = OF_finddevice("/"); | ||||
if (root == -1) { | if (root == -1) { | ||||
device_printf(dev, "failed to get FDT root node\n"); | device_printf(dev, "failed to get FDT root node\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
/* Fixme: Cant find any reference in DTS for dpll_disp_ck@498 for now. */ | |||||
err = clk_get_by_name(dev, "dpll_disp_ck@498", &sc->sc_clk_dpll_disp_ck); | |||||
if (err != 0) { | |||||
device_printf(dev, "Cant get dpll_disp_ck@49\n"); | |||||
return (ENXIO); | |||||
} | |||||
sc->sc_panel.ac_bias = 255; | sc->sc_panel.ac_bias = 255; | ||||
sc->sc_panel.ac_bias_intrpt = 0; | sc->sc_panel.ac_bias_intrpt = 0; | ||||
sc->sc_panel.dma_burst_sz = 16; | sc->sc_panel.dma_burst_sz = 16; | ||||
sc->sc_panel.bpp = 16; | sc->sc_panel.bpp = 16; | ||||
sc->sc_panel.fdd = 128; | sc->sc_panel.fdd = 128; | ||||
sc->sc_panel.sync_edge = 0; | sc->sc_panel.sync_edge = 0; | ||||
sc->sc_panel.sync_ctrl = 1; | sc->sc_panel.sync_ctrl = 1; | ||||
panel_node = fdt_find_compatible(root, "ti,tilcdc,panel", 1); | panel_node = fdt_find_compatible(root, "ti,tilcdc,panel", 1); | ||||
if (panel_node != 0) { | if (panel_node != 0) { | ||||
device_printf(dev, "using static panel info\n"); | device_printf(dev, "using static panel info\n"); | ||||
if (am335x_read_panel_info(dev, panel_node, &sc->sc_panel)) { | if (am335x_read_panel_info(dev, panel_node, &sc->sc_panel)) { | ||||
device_printf(dev, "failed to read panel info\n"); | device_printf(dev, "failed to read panel info\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
if (am335x_read_timing(dev, panel_node, &sc->sc_panel)) { | if (am335x_read_timing(dev, panel_node, &sc->sc_panel)) { | ||||
device_printf(dev, "failed to read timings\n"); | device_printf(dev, "failed to read timings\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
} | } | ||||
ti_prcm_clk_enable(LCDC_CLK); | err = ti_sysc_clock_enable(device_get_parent(dev)); | ||||
if (err != 0) { | |||||
device_printf(dev, "Failed to enable sysc clkctrl, err %d\n", err); | |||||
return (ENXIO); | |||||
} | |||||
rid = 0; | rid = 0; | ||||
sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, | sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, | ||||
RF_ACTIVE); | RF_ACTIVE); | ||||
if (!sc->sc_mem_res) { | if (!sc->sc_mem_res) { | ||||
device_printf(dev, "cannot allocate memory window\n"); | device_printf(dev, "cannot allocate memory window\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | static driver_t am335x_lcd_driver = { | ||||
sizeof(struct am335x_lcd_softc), | sizeof(struct am335x_lcd_softc), | ||||
}; | }; | ||||
static devclass_t am335x_lcd_devclass; | static devclass_t am335x_lcd_devclass; | ||||
DRIVER_MODULE(am335x_lcd, simplebus, am335x_lcd_driver, am335x_lcd_devclass, 0, 0); | DRIVER_MODULE(am335x_lcd, simplebus, am335x_lcd_driver, am335x_lcd_devclass, 0, 0); | ||||
MODULE_VERSION(am335x_lcd, 1); | MODULE_VERSION(am335x_lcd, 1); | ||||
MODULE_DEPEND(am335x_lcd, simplebus, 1, 1, 1); | MODULE_DEPEND(am335x_lcd, simplebus, 1, 1, 1); | ||||
MODULE_DEPEND(am335x_lcd, ti_sysc, 1, 1, 1); |