The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/arm/ti/am335x/am335x_lcd.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright 2013 Oleksandr Tymoshenko <gonzo@freebsd.org>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include "opt_syscons.h"
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/kernel.h>
   36 #include <sys/module.h>
   37 #include <sys/clock.h>
   38 #include <sys/eventhandler.h>
   39 #include <sys/time.h>
   40 #include <sys/bus.h>
   41 #include <sys/lock.h>
   42 #include <sys/mutex.h>
   43 #include <sys/resource.h>
   44 #include <sys/rman.h>
   45 #include <sys/sysctl.h>
   46 #include <vm/vm.h>
   47 #include <vm/pmap.h>
   48 #include <sys/fbio.h>
   49 #include <sys/consio.h>
   50 
   51 #include <machine/bus.h>
   52 
   53 #include <dev/extres/clk/clk.h>
   54 
   55 #include <dev/fdt/fdt_common.h>
   56 #include <dev/ofw/openfirm.h>
   57 #include <dev/ofw/ofw_bus.h>
   58 #include <dev/ofw/ofw_bus_subr.h>
   59 
   60 #include <dev/videomode/videomode.h>
   61 #include <dev/videomode/edidvar.h>
   62 
   63 #include <dev/fb/fbreg.h>
   64 #ifdef DEV_SC
   65 #include <dev/syscons/syscons.h>
   66 #else /* VT */
   67 #include <dev/vt/vt.h>
   68 #endif
   69 
   70 #include <arm/ti/ti_sysc.h>
   71 #include <arm/ti/ti_scm.h>
   72 
   73 #include "am335x_lcd.h"
   74 #include "am335x_pwm.h"
   75 
   76 #include "fb_if.h"
   77 #include "hdmi_if.h"
   78 
   79 #define LCD_PID                 0x00
   80 #define LCD_CTRL                0x04
   81 #define         CTRL_DIV_MASK           0xff
   82 #define         CTRL_DIV_SHIFT          8
   83 #define         CTRL_AUTO_UFLOW_RESTART (1 << 1)
   84 #define         CTRL_RASTER_MODE        1
   85 #define         CTRL_LIDD_MODE          0
   86 #define LCD_LIDD_CTRL           0x0C
   87 #define LCD_LIDD_CS0_CONF       0x10
   88 #define LCD_LIDD_CS0_ADDR       0x14
   89 #define LCD_LIDD_CS0_DATA       0x18
   90 #define LCD_LIDD_CS1_CONF       0x1C
   91 #define LCD_LIDD_CS1_ADDR       0x20
   92 #define LCD_LIDD_CS1_DATA       0x24
   93 #define LCD_RASTER_CTRL         0x28
   94 #define         RASTER_CTRL_TFT24_UNPACKED      (1 << 26)
   95 #define         RASTER_CTRL_TFT24               (1 << 25)
   96 #define         RASTER_CTRL_STN565              (1 << 24)
   97 #define         RASTER_CTRL_TFTPMAP             (1 << 23)
   98 #define         RASTER_CTRL_NIBMODE             (1 << 22)
   99 #define         RASTER_CTRL_PALMODE_SHIFT       20
  100 #define         PALETTE_PALETTE_AND_DATA        0x00
  101 #define         PALETTE_PALETTE_ONLY            0x01
  102 #define         PALETTE_DATA_ONLY               0x02
  103 #define         RASTER_CTRL_REQDLY_SHIFT        12
  104 #define         RASTER_CTRL_MONO8B              (1 << 9)
  105 #define         RASTER_CTRL_RBORDER             (1 << 8)
  106 #define         RASTER_CTRL_LCDTFT              (1 << 7)
  107 #define         RASTER_CTRL_LCDBW               (1 << 1)
  108 #define         RASTER_CTRL_LCDEN               (1 << 0)
  109 #define LCD_RASTER_TIMING_0     0x2C
  110 #define         RASTER_TIMING_0_HBP_SHIFT       24
  111 #define         RASTER_TIMING_0_HFP_SHIFT       16
  112 #define         RASTER_TIMING_0_HSW_SHIFT       10
  113 #define         RASTER_TIMING_0_PPLLSB_SHIFT    4
  114 #define         RASTER_TIMING_0_PPLMSB_SHIFT    3
  115 #define LCD_RASTER_TIMING_1     0x30
  116 #define         RASTER_TIMING_1_VBP_SHIFT       24
  117 #define         RASTER_TIMING_1_VFP_SHIFT       16
  118 #define         RASTER_TIMING_1_VSW_SHIFT       10
  119 #define         RASTER_TIMING_1_LPP_SHIFT       0
  120 #define LCD_RASTER_TIMING_2     0x34
  121 #define         RASTER_TIMING_2_HSWHI_SHIFT     27
  122 #define         RASTER_TIMING_2_LPP_B10_SHIFT   26
  123 #define         RASTER_TIMING_2_PHSVS           (1 << 25)
  124 #define         RASTER_TIMING_2_PHSVS_RISE      (1 << 24)
  125 #define         RASTER_TIMING_2_PHSVS_FALL      (0 << 24)
  126 #define         RASTER_TIMING_2_IOE             (1 << 23)
  127 #define         RASTER_TIMING_2_IPC             (1 << 22)
  128 #define         RASTER_TIMING_2_IHS             (1 << 21)
  129 #define         RASTER_TIMING_2_IVS             (1 << 20)
  130 #define         RASTER_TIMING_2_ACBI_SHIFT      16
  131 #define         RASTER_TIMING_2_ACB_SHIFT       8
  132 #define         RASTER_TIMING_2_HBPHI_SHIFT     4
  133 #define         RASTER_TIMING_2_HFPHI_SHIFT     0
  134 #define LCD_RASTER_SUBPANEL     0x38
  135 #define LCD_RASTER_SUBPANEL2    0x3C
  136 #define LCD_LCDDMA_CTRL         0x40
  137 #define         LCDDMA_CTRL_DMA_MASTER_PRIO_SHIFT               16
  138 #define         LCDDMA_CTRL_TH_FIFO_RDY_SHIFT   8
  139 #define         LCDDMA_CTRL_BURST_SIZE_SHIFT    4
  140 #define         LCDDMA_CTRL_BYTES_SWAP          (1 << 3)
  141 #define         LCDDMA_CTRL_BE                  (1 << 1)
  142 #define         LCDDMA_CTRL_FB0_ONLY            0
  143 #define         LCDDMA_CTRL_FB0_FB1             (1 << 0)
  144 #define LCD_LCDDMA_FB0_BASE     0x44
  145 #define LCD_LCDDMA_FB0_CEILING  0x48
  146 #define LCD_LCDDMA_FB1_BASE     0x4C
  147 #define LCD_LCDDMA_FB1_CEILING  0x50
  148 #define LCD_SYSCONFIG           0x54
  149 #define         SYSCONFIG_STANDBY_FORCE         (0 << 4)
  150 #define         SYSCONFIG_STANDBY_NONE          (1 << 4)
  151 #define         SYSCONFIG_STANDBY_SMART         (2 << 4)
  152 #define         SYSCONFIG_IDLE_FORCE            (0 << 2)
  153 #define         SYSCONFIG_IDLE_NONE             (1 << 2)
  154 #define         SYSCONFIG_IDLE_SMART            (2 << 2)
  155 #define LCD_IRQSTATUS_RAW       0x58
  156 #define LCD_IRQSTATUS           0x5C
  157 #define LCD_IRQENABLE_SET       0x60
  158 #define LCD_IRQENABLE_CLEAR     0x64
  159 #define         IRQ_EOF1                (1 << 9)
  160 #define         IRQ_EOF0                (1 << 8)
  161 #define         IRQ_PL                  (1 << 6)
  162 #define         IRQ_FUF                 (1 << 5)
  163 #define         IRQ_ACB                 (1 << 3)
  164 #define         IRQ_SYNC_LOST           (1 << 2)
  165 #define         IRQ_RASTER_DONE         (1 << 1)
  166 #define         IRQ_FRAME_DONE          (1 << 0)
  167 #define LCD_END_OF_INT_IND      0x68
  168 #define LCD_CLKC_ENABLE         0x6C
  169 #define         CLKC_ENABLE_DMA         (1 << 2)
  170 #define         CLKC_ENABLE_LDID        (1 << 1)
  171 #define         CLKC_ENABLE_CORE        (1 << 0)
  172 #define LCD_CLKC_RESET          0x70
  173 #define         CLKC_RESET_MAIN         (1 << 3)
  174 #define         CLKC_RESET_DMA          (1 << 2)
  175 #define         CLKC_RESET_LDID         (1 << 1)
  176 #define         CLKC_RESET_CORE         (1 << 0)
  177 
  178 #define LCD_LOCK(_sc)           mtx_lock(&(_sc)->sc_mtx)
  179 #define LCD_UNLOCK(_sc)         mtx_unlock(&(_sc)->sc_mtx)
  180 #define LCD_LOCK_INIT(_sc)      mtx_init(&(_sc)->sc_mtx, \
  181     device_get_nameunit(_sc->sc_dev), "am335x_lcd", MTX_DEF)
  182 #define LCD_LOCK_DESTROY(_sc)   mtx_destroy(&(_sc)->sc_mtx);
  183 
  184 #define LCD_READ4(_sc, reg)     bus_read_4((_sc)->sc_mem_res, reg);
  185 #define LCD_WRITE4(_sc, reg, value)     \
  186     bus_write_4((_sc)->sc_mem_res, reg, value);
  187 
  188 /* Backlight is controlled by eCAS interface on PWM unit 0 */
  189 #define PWM_UNIT        0
  190 #define PWM_PERIOD      100
  191 
  192 #define MODE_HBP(mode)  ((mode)->htotal - (mode)->hsync_end)
  193 #define MODE_HFP(mode)  ((mode)->hsync_start - (mode)->hdisplay)
  194 #define MODE_HSW(mode)  ((mode)->hsync_end - (mode)->hsync_start)
  195 #define MODE_VBP(mode)  ((mode)->vtotal - (mode)->vsync_end)
  196 #define MODE_VFP(mode)  ((mode)->vsync_start - (mode)->vdisplay)
  197 #define MODE_VSW(mode)  ((mode)->vsync_end - (mode)->vsync_start)
  198 
  199 #define MAX_PIXEL_CLOCK 126000
  200 #define MAX_BANDWIDTH   (1280*1024*60)
  201 
  202 struct am335x_lcd_softc {
  203         device_t                sc_dev;
  204         struct fb_info          sc_fb_info;
  205         struct resource         *sc_mem_res;
  206         struct resource         *sc_irq_res;
  207         void                    *sc_intr_hl;
  208         struct mtx              sc_mtx;
  209         int                     sc_backlight;
  210         struct sysctl_oid       *sc_oid;
  211 
  212         struct panel_info       sc_panel;
  213 
  214         /* Framebuffer */
  215         bus_dma_tag_t           sc_dma_tag;
  216         bus_dmamap_t            sc_dma_map;
  217         size_t                  sc_fb_size;
  218         bus_addr_t              sc_fb_phys;
  219         uint8_t                 *sc_fb_base;
  220 
  221         /* HDMI framer */
  222         phandle_t               sc_hdmi_framer;
  223         eventhandler_tag        sc_hdmi_evh;
  224 
  225         /* Clock */
  226         clk_t                   sc_clk_dpll_disp_ck;
  227 };
  228 
  229 static void
  230 am335x_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
  231 {
  232         bus_addr_t *addr;
  233 
  234         if (err)
  235                 return;
  236 
  237         addr = (bus_addr_t*)arg;
  238         *addr = segs[0].ds_addr;
  239 }
  240 
  241 static uint32_t
  242 am335x_lcd_calc_divisor(uint32_t reference, uint32_t freq)
  243 {
  244         uint32_t div, i;
  245         uint32_t delta, min_delta;
  246 
  247         min_delta = freq;
  248         div = 255;
  249 
  250         /* Raster mode case: divisors are in range from 2 to 255 */
  251         for (i = 2; i < 255; i++) {
  252                 delta = abs(reference/i - freq);
  253                 if (delta < min_delta) {
  254                         div = i;
  255                         min_delta = delta;
  256                 }
  257         }
  258 
  259         return (div);
  260 }
  261 
  262 static int
  263 am335x_lcd_sysctl_backlight(SYSCTL_HANDLER_ARGS)
  264 {
  265         struct am335x_lcd_softc *sc = (struct am335x_lcd_softc*)arg1;
  266         int error;
  267         int backlight;
  268 
  269         backlight = sc->sc_backlight;
  270         error = sysctl_handle_int(oidp, &backlight, 0, req);
  271 
  272         if (error != 0 || req->newptr == NULL)
  273                 return (error);
  274 
  275         if (backlight < 0)
  276                 backlight = 0;
  277         if (backlight > 100)
  278                 backlight = 100;
  279 
  280         LCD_LOCK(sc);
  281         error = am335x_pwm_config_ecap(PWM_UNIT, PWM_PERIOD,
  282             backlight*PWM_PERIOD/100);
  283         if (error == 0)
  284                 sc->sc_backlight = backlight;
  285         LCD_UNLOCK(sc);
  286 
  287         return (error);
  288 }
  289 
  290 static uint32_t
  291 am335x_mode_vrefresh(const struct videomode *mode)
  292 {
  293         uint32_t refresh;
  294 
  295         /* Calculate vertical refresh rate */
  296         refresh = (mode->dot_clock * 1000 / mode->htotal);
  297         refresh = (refresh + mode->vtotal / 2) / mode->vtotal;
  298 
  299         if (mode->flags & VID_INTERLACE)
  300                 refresh *= 2;
  301         if (mode->flags & VID_DBLSCAN)
  302                 refresh /= 2;
  303 
  304         return refresh;
  305 }
  306 
  307 static int
  308 am335x_mode_is_valid(const struct videomode *mode)
  309 {
  310         uint32_t hbp, hfp, hsw;
  311         uint32_t vbp, vfp, vsw;
  312 
  313         if (mode->dot_clock > MAX_PIXEL_CLOCK)
  314                 return (0);
  315 
  316         if (mode->hdisplay & 0xf)
  317                 return (0);
  318 
  319         if (mode->vdisplay > 2048)
  320                 return (0);
  321 
  322         /* Check ranges for timing parameters */
  323         hbp = MODE_HBP(mode) - 1;
  324         hfp = MODE_HFP(mode) - 1;
  325         hsw = MODE_HSW(mode) - 1;
  326         vbp = MODE_VBP(mode);
  327         vfp = MODE_VFP(mode);
  328         vsw = MODE_VSW(mode) - 1;
  329 
  330         if (hbp > 0x3ff)
  331                 return (0);
  332         if (hfp > 0x3ff)
  333                 return (0);
  334         if (hsw > 0x3ff)
  335                 return (0);
  336 
  337         if (vbp > 0xff)
  338                 return (0);
  339         if (vfp > 0xff)
  340                 return (0);
  341         if (vsw > 0x3f)
  342                 return (0);
  343         if (mode->vdisplay*mode->hdisplay*am335x_mode_vrefresh(mode) 
  344             > MAX_BANDWIDTH)
  345                 return (0);
  346 
  347         return (1);
  348 }
  349 
  350 static void
  351 am335x_read_hdmi_property(device_t dev)
  352 {
  353         phandle_t node, xref;
  354         phandle_t endpoint;
  355         phandle_t hdmi_xref;
  356         struct am335x_lcd_softc *sc;
  357 
  358         sc = device_get_softc(dev);
  359         node = ofw_bus_get_node(dev);
  360         sc->sc_hdmi_framer = 0;
  361 
  362         /*
  363          * Old FreeBSD way of referencing to HDMI framer
  364          */
  365         if (OF_getencprop(node, "hdmi", &hdmi_xref, sizeof(hdmi_xref)) != -1) {
  366                 sc->sc_hdmi_framer = hdmi_xref;
  367                 return;
  368         }
  369 
  370         /*
  371          * Use bindings described in Linux docs:
  372          * bindings/media/video-interfaces.txt
  373          * We assume that the only endpoint in LCDC node
  374          * is HDMI framer.
  375          */
  376         node = ofw_bus_find_child(node, "port");
  377 
  378         /* No media bindings */
  379         if (node == 0)
  380                 return;
  381 
  382         for (endpoint = OF_child(node); endpoint != 0; endpoint = OF_peer(endpoint)) {
  383                 if (OF_getencprop(endpoint, "remote-endpoint", &xref, sizeof(xref)) != -1) {
  384                         /* port/port@0/endpoint@0 */
  385                         node = OF_node_from_xref(xref);
  386                         /* port/port@0 */
  387                         node = OF_parent(node);
  388                         /* port */
  389                         node = OF_parent(node);
  390                         /* actual owner of port, in our case HDMI framer */
  391                         sc->sc_hdmi_framer = OF_xref_from_node(OF_parent(node));
  392                         if (sc->sc_hdmi_framer != 0)
  393                                 return;
  394                 }
  395         }
  396 }
  397 
  398 static int
  399 am335x_read_property(device_t dev, phandle_t node, const char *name, uint32_t *val)
  400 {
  401         pcell_t cell;
  402 
  403         if ((OF_getencprop(node, name, &cell, sizeof(cell))) <= 0) {
  404                 device_printf(dev, "missing '%s' attribute in LCD panel info\n",
  405                     name);
  406                 return (ENXIO);
  407         }
  408 
  409         *val = cell;
  410 
  411         return (0);
  412 }
  413 
  414 static int
  415 am335x_read_timing(device_t dev, phandle_t node, struct panel_info *panel)
  416 {
  417         int error;
  418         phandle_t timings_node, timing_node, native;
  419 
  420         timings_node = ofw_bus_find_child(node, "display-timings");
  421         if (timings_node == 0) {
  422                 device_printf(dev, "no \"display-timings\" node\n");
  423                 return (-1);
  424         }
  425 
  426         if (OF_searchencprop(timings_node, "native-mode", &native,
  427             sizeof(native)) == -1) {
  428                 device_printf(dev, "no \"native-mode\" reference in \"timings\" node\n");
  429                 return (-1);
  430         }
  431 
  432         timing_node = OF_node_from_xref(native);
  433 
  434         error = 0;
  435         if ((error = am335x_read_property(dev, timing_node,
  436             "hactive", &panel->panel_width)))
  437                 goto out;
  438 
  439         if ((error = am335x_read_property(dev, timing_node,
  440             "vactive", &panel->panel_height)))
  441                 goto out;
  442 
  443         if ((error = am335x_read_property(dev, timing_node,
  444             "hfront-porch", &panel->panel_hfp)))
  445                 goto out;
  446 
  447         if ((error = am335x_read_property(dev, timing_node,
  448             "hback-porch", &panel->panel_hbp)))
  449                 goto out;
  450 
  451         if ((error = am335x_read_property(dev, timing_node,
  452             "hsync-len", &panel->panel_hsw)))
  453                 goto out;
  454 
  455         if ((error = am335x_read_property(dev, timing_node,
  456             "vfront-porch", &panel->panel_vfp)))
  457                 goto out;
  458 
  459         if ((error = am335x_read_property(dev, timing_node,
  460             "vback-porch", &panel->panel_vbp)))
  461                 goto out;
  462 
  463         if ((error = am335x_read_property(dev, timing_node,
  464             "vsync-len", &panel->panel_vsw)))
  465                 goto out;
  466 
  467         if ((error = am335x_read_property(dev, timing_node,
  468             "clock-frequency", &panel->panel_pxl_clk)))
  469                 goto out;
  470 
  471         if ((error = am335x_read_property(dev, timing_node,
  472             "pixelclk-active", &panel->pixelclk_active)))
  473                 goto out;
  474 
  475         if ((error = am335x_read_property(dev, timing_node,
  476             "hsync-active", &panel->hsync_active)))
  477                 goto out;
  478 
  479         if ((error = am335x_read_property(dev, timing_node,
  480             "vsync-active", &panel->vsync_active)))
  481                 goto out;
  482 
  483 out:
  484         return (error);
  485 }
  486 
  487 static int
  488 am335x_read_panel_info(device_t dev, phandle_t node, struct panel_info *panel)
  489 {
  490         phandle_t panel_info_node;
  491 
  492         panel_info_node = ofw_bus_find_child(node, "panel-info");
  493         if (panel_info_node == 0)
  494                 return (-1);
  495 
  496         am335x_read_property(dev, panel_info_node,
  497             "ac-bias", &panel->ac_bias);
  498 
  499         am335x_read_property(dev, panel_info_node,
  500             "ac-bias-intrpt", &panel->ac_bias_intrpt);
  501 
  502         am335x_read_property(dev, panel_info_node,
  503             "dma-burst-sz", &panel->dma_burst_sz);
  504 
  505         am335x_read_property(dev, panel_info_node,
  506             "bpp", &panel->bpp);
  507 
  508         am335x_read_property(dev, panel_info_node,
  509             "fdd", &panel->fdd);
  510 
  511         am335x_read_property(dev, panel_info_node,
  512             "sync-edge", &panel->sync_edge);
  513 
  514         am335x_read_property(dev, panel_info_node,
  515             "sync-ctrl", &panel->sync_ctrl);
  516 
  517         return (0);
  518 }
  519 
  520 static void
  521 am335x_lcd_intr(void *arg)
  522 {
  523         struct am335x_lcd_softc *sc = arg;
  524         uint32_t reg; 
  525 
  526         reg = LCD_READ4(sc, LCD_IRQSTATUS);
  527         LCD_WRITE4(sc, LCD_IRQSTATUS, reg);
  528         /* Read value back to make sure it reached the hardware */
  529         reg = LCD_READ4(sc, LCD_IRQSTATUS);
  530 
  531         if (reg & IRQ_SYNC_LOST) {
  532                 reg = LCD_READ4(sc, LCD_RASTER_CTRL);
  533                 reg &= ~RASTER_CTRL_LCDEN;
  534                 LCD_WRITE4(sc, LCD_RASTER_CTRL, reg); 
  535 
  536                 reg = LCD_READ4(sc, LCD_RASTER_CTRL);
  537                 reg |= RASTER_CTRL_LCDEN;
  538                 LCD_WRITE4(sc, LCD_RASTER_CTRL, reg); 
  539                 goto done;
  540         }
  541 
  542         if (reg & IRQ_PL) {
  543                 reg = LCD_READ4(sc, LCD_RASTER_CTRL);
  544                 reg &= ~RASTER_CTRL_LCDEN;
  545                 LCD_WRITE4(sc, LCD_RASTER_CTRL, reg); 
  546 
  547                 reg = LCD_READ4(sc, LCD_RASTER_CTRL);
  548                 reg |= RASTER_CTRL_LCDEN;
  549                 LCD_WRITE4(sc, LCD_RASTER_CTRL, reg); 
  550                 goto done;
  551         }
  552 
  553         if (reg & IRQ_EOF0) {
  554                 LCD_WRITE4(sc, LCD_LCDDMA_FB0_BASE, sc->sc_fb_phys); 
  555                 LCD_WRITE4(sc, LCD_LCDDMA_FB0_CEILING, sc->sc_fb_phys + sc->sc_fb_size - 1); 
  556                 reg &= ~IRQ_EOF0;
  557         }
  558 
  559         if (reg & IRQ_EOF1) {
  560                 LCD_WRITE4(sc, LCD_LCDDMA_FB1_BASE, sc->sc_fb_phys); 
  561                 LCD_WRITE4(sc, LCD_LCDDMA_FB1_CEILING, sc->sc_fb_phys + sc->sc_fb_size - 1); 
  562                 reg &= ~IRQ_EOF1;
  563         }
  564 
  565         if (reg & IRQ_FUF) {
  566                 /* TODO: Handle FUF */
  567         }
  568 
  569         if (reg & IRQ_ACB) {
  570                 /* TODO: Handle ACB */
  571         }
  572 
  573 done:
  574         LCD_WRITE4(sc, LCD_END_OF_INT_IND, 0);
  575         /* Read value back to make sure it reached the hardware */
  576         reg = LCD_READ4(sc, LCD_END_OF_INT_IND);
  577 }
  578 
  579 static const struct videomode *
  580 am335x_lcd_pick_mode(struct edid_info *ei)
  581 {
  582         const struct videomode *videomode;
  583         const struct videomode *m;
  584         int n;
  585 
  586         /* Get standard VGA as default */
  587         videomode = NULL;
  588 
  589         /*
  590          * Pick a mode.
  591          */
  592         if (ei->edid_preferred_mode != NULL) {
  593                 if (am335x_mode_is_valid(ei->edid_preferred_mode))
  594                         videomode = ei->edid_preferred_mode;
  595         }
  596 
  597         if (videomode == NULL) {
  598                 m = ei->edid_modes;
  599 
  600                 sort_modes(ei->edid_modes,
  601                     &ei->edid_preferred_mode,
  602                     ei->edid_nmodes);
  603                 for (n = 0; n < ei->edid_nmodes; n++)
  604                         if (am335x_mode_is_valid(&m[n])) {
  605                                 videomode = &m[n];
  606                                 break;
  607                         }
  608         }
  609 
  610         return videomode;
  611 }
  612 
  613 static int
  614 am335x_lcd_configure(struct am335x_lcd_softc *sc)
  615 {
  616         int div;
  617         uint32_t reg, timing0, timing1, timing2;
  618         uint32_t burst_log;
  619         size_t dma_size;
  620         uint32_t hbp, hfp, hsw;
  621         uint32_t vbp, vfp, vsw;
  622         uint32_t width, height;
  623         uint64_t ref_freq;
  624         int err;
  625 
  626         /*
  627          * try to adjust clock to get double of requested frequency
  628          * HDMI/DVI displays are very sensitive to error in frequncy value
  629          */
  630 
  631         err = clk_set_freq(sc->sc_clk_dpll_disp_ck, sc->sc_panel.panel_pxl_clk*2,
  632             CLK_SET_ROUND_ANY);
  633         if (err != 0) {
  634                 device_printf(sc->sc_dev, "can't set source frequency\n");
  635                 return (ENXIO);
  636         }
  637 
  638         err = clk_get_freq(sc->sc_clk_dpll_disp_ck, &ref_freq);
  639         if (err != 0) {
  640                 device_printf(sc->sc_dev, "can't get reference frequency\n");
  641                 return (ENXIO);
  642         }
  643 
  644         /* Panel initialization */
  645         dma_size = round_page(sc->sc_panel.panel_width*sc->sc_panel.panel_height*sc->sc_panel.bpp/8);
  646 
  647         /*
  648          * Now allocate framebuffer memory
  649          */
  650         err = bus_dma_tag_create(
  651             bus_get_dma_tag(sc->sc_dev),
  652             4, 0,               /* alignment, boundary */
  653             BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
  654             BUS_SPACE_MAXADDR,          /* highaddr */
  655             NULL, NULL,                 /* filter, filterarg */
  656             dma_size, 1,                        /* maxsize, nsegments */
  657             dma_size, 0,                        /* maxsegsize, flags */
  658             NULL, NULL,                 /* lockfunc, lockarg */
  659             &sc->sc_dma_tag);
  660         if (err)
  661                 goto done;
  662 
  663         err = bus_dmamem_alloc(sc->sc_dma_tag, (void **)&sc->sc_fb_base,
  664             BUS_DMA_COHERENT, &sc->sc_dma_map);
  665 
  666         if (err) {
  667                 device_printf(sc->sc_dev, "cannot allocate framebuffer\n");
  668                 goto done;
  669         }
  670 
  671         err = bus_dmamap_load(sc->sc_dma_tag, sc->sc_dma_map, sc->sc_fb_base,
  672             dma_size, am335x_fb_dmamap_cb, &sc->sc_fb_phys, BUS_DMA_NOWAIT);
  673 
  674         if (err) {
  675                 device_printf(sc->sc_dev, "cannot load DMA map\n");
  676                 goto done;
  677         }
  678 
  679         /* Make sure it's blank */
  680         memset(sc->sc_fb_base, 0x0, dma_size);
  681 
  682         /* Calculate actual FB Size */
  683         sc->sc_fb_size = sc->sc_panel.panel_width*sc->sc_panel.panel_height*sc->sc_panel.bpp/8;
  684 
  685         /* Only raster mode is supported */
  686         reg = CTRL_RASTER_MODE;
  687         div = am335x_lcd_calc_divisor(ref_freq, sc->sc_panel.panel_pxl_clk);
  688         reg |= (div << CTRL_DIV_SHIFT);
  689         LCD_WRITE4(sc, LCD_CTRL, reg); 
  690 
  691         /* Set timing */
  692         timing0 = timing1 = timing2 = 0;
  693 
  694         hbp = sc->sc_panel.panel_hbp - 1;
  695         hfp = sc->sc_panel.panel_hfp - 1;
  696         hsw = sc->sc_panel.panel_hsw - 1;
  697 
  698         vbp = sc->sc_panel.panel_vbp;
  699         vfp = sc->sc_panel.panel_vfp;
  700         vsw = sc->sc_panel.panel_vsw - 1;
  701 
  702         height = sc->sc_panel.panel_height - 1;
  703         width = sc->sc_panel.panel_width - 1;
  704 
  705         /* Horizontal back porch */
  706         timing0 |= (hbp & 0xff) << RASTER_TIMING_0_HBP_SHIFT;
  707         timing2 |= ((hbp >> 8) & 3) << RASTER_TIMING_2_HBPHI_SHIFT;
  708         /* Horizontal front porch */
  709         timing0 |= (hfp & 0xff) << RASTER_TIMING_0_HFP_SHIFT;
  710         timing2 |= ((hfp >> 8) & 3) << RASTER_TIMING_2_HFPHI_SHIFT;
  711         /* Horizontal sync width */
  712         timing0 |= (hsw & 0x3f) << RASTER_TIMING_0_HSW_SHIFT;
  713         timing2 |= ((hsw >> 6) & 0xf) << RASTER_TIMING_2_HSWHI_SHIFT;
  714 
  715         /* Vertical back porch, front porch, sync width */
  716         timing1 |= (vbp & 0xff) << RASTER_TIMING_1_VBP_SHIFT;
  717         timing1 |= (vfp & 0xff) << RASTER_TIMING_1_VFP_SHIFT;
  718         timing1 |= (vsw & 0x3f) << RASTER_TIMING_1_VSW_SHIFT;
  719 
  720         /* Pixels per line */
  721         timing0 |= ((width >> 10) & 1)
  722             << RASTER_TIMING_0_PPLMSB_SHIFT;
  723         timing0 |= ((width >> 4) & 0x3f)
  724             << RASTER_TIMING_0_PPLLSB_SHIFT;
  725 
  726         /* Lines per panel */
  727         timing1 |= (height & 0x3ff) 
  728             << RASTER_TIMING_1_LPP_SHIFT;
  729         timing2 |= ((height >> 10 ) & 1) 
  730             << RASTER_TIMING_2_LPP_B10_SHIFT;
  731 
  732         /* clock signal settings */
  733         if (sc->sc_panel.sync_ctrl)
  734                 timing2 |= RASTER_TIMING_2_PHSVS;
  735         if (sc->sc_panel.sync_edge)
  736                 timing2 |= RASTER_TIMING_2_PHSVS_RISE;
  737         else
  738                 timing2 |= RASTER_TIMING_2_PHSVS_FALL;
  739         if (sc->sc_panel.hsync_active == 0)
  740                 timing2 |= RASTER_TIMING_2_IHS;
  741         if (sc->sc_panel.vsync_active == 0)
  742                 timing2 |= RASTER_TIMING_2_IVS;
  743         if (sc->sc_panel.pixelclk_active == 0)
  744                 timing2 |= RASTER_TIMING_2_IPC;
  745 
  746         /* AC bias */
  747         timing2 |= (sc->sc_panel.ac_bias << RASTER_TIMING_2_ACB_SHIFT);
  748         timing2 |= (sc->sc_panel.ac_bias_intrpt << RASTER_TIMING_2_ACBI_SHIFT);
  749 
  750         LCD_WRITE4(sc, LCD_RASTER_TIMING_0, timing0); 
  751         LCD_WRITE4(sc, LCD_RASTER_TIMING_1, timing1); 
  752         LCD_WRITE4(sc, LCD_RASTER_TIMING_2, timing2); 
  753 
  754         /* DMA settings */
  755         reg = LCDDMA_CTRL_FB0_FB1;
  756         /* Find power of 2 for current burst size */
  757         switch (sc->sc_panel.dma_burst_sz) {
  758         case 1:
  759                 burst_log = 0;
  760                 break;
  761         case 2:
  762                 burst_log = 1;
  763                 break;
  764         case 4:
  765                 burst_log = 2;
  766                 break;
  767         case 8:
  768                 burst_log = 3;
  769                 break;
  770         case 16:
  771         default:
  772                 burst_log = 4;
  773                 break;
  774         }
  775         reg |= (burst_log << LCDDMA_CTRL_BURST_SIZE_SHIFT);
  776         /* XXX: FIFO TH */
  777         reg |= (0 << LCDDMA_CTRL_TH_FIFO_RDY_SHIFT);
  778         LCD_WRITE4(sc, LCD_LCDDMA_CTRL, reg); 
  779 
  780         LCD_WRITE4(sc, LCD_LCDDMA_FB0_BASE, sc->sc_fb_phys); 
  781         LCD_WRITE4(sc, LCD_LCDDMA_FB0_CEILING, sc->sc_fb_phys + sc->sc_fb_size - 1); 
  782         LCD_WRITE4(sc, LCD_LCDDMA_FB1_BASE, sc->sc_fb_phys); 
  783         LCD_WRITE4(sc, LCD_LCDDMA_FB1_CEILING, sc->sc_fb_phys + sc->sc_fb_size - 1); 
  784 
  785         /* Enable LCD */
  786         reg = RASTER_CTRL_LCDTFT;
  787         reg |= (sc->sc_panel.fdd << RASTER_CTRL_REQDLY_SHIFT);
  788         reg |= (PALETTE_DATA_ONLY << RASTER_CTRL_PALMODE_SHIFT);
  789         if (sc->sc_panel.bpp >= 24)
  790                 reg |= RASTER_CTRL_TFT24;
  791         if (sc->sc_panel.bpp == 32)
  792                 reg |= RASTER_CTRL_TFT24_UNPACKED;
  793         LCD_WRITE4(sc, LCD_RASTER_CTRL, reg); 
  794 
  795         LCD_WRITE4(sc, LCD_CLKC_ENABLE,
  796             CLKC_ENABLE_DMA | CLKC_ENABLE_LDID | CLKC_ENABLE_CORE);
  797 
  798         LCD_WRITE4(sc, LCD_CLKC_RESET, CLKC_RESET_MAIN);
  799         DELAY(100);
  800         LCD_WRITE4(sc, LCD_CLKC_RESET, 0);
  801 
  802         reg = IRQ_EOF1 | IRQ_EOF0 | IRQ_FUF | IRQ_PL |
  803             IRQ_ACB | IRQ_SYNC_LOST |  IRQ_RASTER_DONE |
  804             IRQ_FRAME_DONE;
  805         LCD_WRITE4(sc, LCD_IRQENABLE_SET, reg);
  806 
  807         reg = LCD_READ4(sc, LCD_RASTER_CTRL);
  808         reg |= RASTER_CTRL_LCDEN;
  809         LCD_WRITE4(sc, LCD_RASTER_CTRL, reg); 
  810 
  811         LCD_WRITE4(sc, LCD_SYSCONFIG,
  812             SYSCONFIG_STANDBY_SMART | SYSCONFIG_IDLE_SMART); 
  813 
  814         sc->sc_fb_info.fb_name = device_get_nameunit(sc->sc_dev);
  815         sc->sc_fb_info.fb_vbase = (intptr_t)sc->sc_fb_base;
  816         sc->sc_fb_info.fb_pbase = sc->sc_fb_phys;
  817         sc->sc_fb_info.fb_size = sc->sc_fb_size;
  818         sc->sc_fb_info.fb_bpp = sc->sc_fb_info.fb_depth = sc->sc_panel.bpp;
  819         sc->sc_fb_info.fb_stride = sc->sc_panel.panel_width*sc->sc_panel.bpp / 8;
  820         sc->sc_fb_info.fb_width = sc->sc_panel.panel_width;
  821         sc->sc_fb_info.fb_height = sc->sc_panel.panel_height;
  822 
  823 #ifdef  DEV_SC
  824         err = (sc_attach_unit(device_get_unit(sc->sc_dev),
  825             device_get_flags(sc->sc_dev) | SC_AUTODETECT_KBD));
  826 
  827         if (err) {
  828                 device_printf(sc->sc_dev, "failed to attach syscons\n");
  829                 goto fail;
  830         }
  831 
  832         am335x_lcd_syscons_setup((vm_offset_t)sc->sc_fb_base, sc->sc_fb_phys, &panel);
  833 #else /* VT */
  834         device_t fbd = device_add_child(sc->sc_dev, "fbd",
  835         device_get_unit(sc->sc_dev));
  836         if (fbd != NULL) {
  837                 if (device_probe_and_attach(fbd) != 0)
  838                         device_printf(sc->sc_dev, "failed to attach fbd device\n");
  839         } else
  840                 device_printf(sc->sc_dev, "failed to add fbd child\n");
  841 #endif
  842 
  843 done:
  844         return (err);
  845 }
  846 
  847 static void
  848 am335x_lcd_hdmi_event(void *arg, device_t hdmi, int event)
  849 {
  850         struct am335x_lcd_softc *sc;
  851         const struct videomode *videomode;
  852         struct videomode hdmi_mode;
  853         device_t hdmi_dev;
  854         uint8_t *edid;
  855         uint32_t edid_len;
  856         struct edid_info ei;
  857 
  858         sc = arg;
  859 
  860         /* Nothing to work with */
  861         if (!sc->sc_hdmi_framer) {
  862                 device_printf(sc->sc_dev, "HDMI event without HDMI framer set\n");
  863                 return;
  864         }
  865 
  866         hdmi_dev = OF_device_from_xref(sc->sc_hdmi_framer);
  867         if (!hdmi_dev) {
  868                 device_printf(sc->sc_dev, "no actual device for \"hdmi\" property\n");
  869                 return;
  870         }
  871 
  872         edid = NULL;
  873         edid_len = 0;
  874         if (HDMI_GET_EDID(hdmi_dev, &edid, &edid_len) != 0) {
  875                 device_printf(sc->sc_dev, "failed to get EDID info from HDMI framer\n");
  876                 return;
  877         }
  878 
  879         videomode = NULL;
  880 
  881         if (edid_parse(edid, &ei) == 0) {
  882                 edid_print(&ei);
  883                 videomode = am335x_lcd_pick_mode(&ei);
  884         } else
  885                 device_printf(sc->sc_dev, "failed to parse EDID\n");
  886 
  887         /* Use standard VGA as fallback */
  888         if (videomode == NULL)
  889                 videomode = pick_mode_by_ref(640, 480, 60);
  890 
  891         if (videomode == NULL) {
  892                 device_printf(sc->sc_dev, "failed to find usable videomode");
  893                 return;
  894         }
  895 
  896         device_printf(sc->sc_dev, "detected videomode: %dx%d @ %dKHz\n", videomode->hdisplay,
  897                 videomode->vdisplay, am335x_mode_vrefresh(videomode));
  898 
  899         sc->sc_panel.panel_width = videomode->hdisplay;
  900         sc->sc_panel.panel_height = videomode->vdisplay;
  901         sc->sc_panel.panel_hfp = videomode->hsync_start - videomode->hdisplay;
  902         sc->sc_panel.panel_hbp = videomode->htotal - videomode->hsync_end;
  903         sc->sc_panel.panel_hsw = videomode->hsync_end - videomode->hsync_start;
  904         sc->sc_panel.panel_vfp = videomode->vsync_start - videomode->vdisplay;
  905         sc->sc_panel.panel_vbp = videomode->vtotal - videomode->vsync_end;
  906         sc->sc_panel.panel_vsw = videomode->vsync_end - videomode->vsync_start;
  907         sc->sc_panel.pixelclk_active = 1;
  908 
  909         /* logic for HSYNC should be reversed */
  910         if (videomode->flags & VID_NHSYNC)
  911                 sc->sc_panel.hsync_active = 1;
  912         else
  913                 sc->sc_panel.hsync_active = 0;
  914 
  915         if (videomode->flags & VID_NVSYNC)
  916                 sc->sc_panel.vsync_active = 0;
  917         else
  918                 sc->sc_panel.vsync_active = 1;
  919 
  920         sc->sc_panel.panel_pxl_clk = videomode->dot_clock * 1000;
  921 
  922         am335x_lcd_configure(sc);
  923 
  924         memcpy(&hdmi_mode, videomode, sizeof(hdmi_mode));
  925         hdmi_mode.hskew = videomode->hsync_end - videomode->hsync_start;
  926         hdmi_mode.flags |= VID_HSKEW;
  927 
  928         HDMI_SET_VIDEOMODE(hdmi_dev, &hdmi_mode);
  929 }
  930 
  931 static int
  932 am335x_lcd_probe(device_t dev)
  933 {
  934 #ifdef DEV_SC
  935         int err;
  936 #endif
  937 
  938         if (!ofw_bus_status_okay(dev))
  939                 return (ENXIO);
  940 
  941         if (!ofw_bus_is_compatible(dev, "ti,am33xx-tilcdc"))
  942                 return (ENXIO);
  943 
  944         device_set_desc(dev, "AM335x LCD controller");
  945 
  946 #ifdef DEV_SC
  947         err = sc_probe_unit(device_get_unit(dev), 
  948             device_get_flags(dev) | SC_AUTODETECT_KBD);
  949         if (err != 0)
  950                 return (err);
  951 #endif
  952 
  953         return (BUS_PROBE_DEFAULT);
  954 }
  955 
  956 static int
  957 am335x_lcd_attach(device_t dev)
  958 {
  959         struct am335x_lcd_softc *sc;
  960 
  961         int err;
  962         int rid;
  963         struct sysctl_ctx_list *ctx;
  964         struct sysctl_oid *tree;
  965         phandle_t root, panel_node;
  966 
  967         err = 0;
  968         sc = device_get_softc(dev);
  969         sc->sc_dev = dev;
  970 
  971         am335x_read_hdmi_property(dev);
  972 
  973         root = OF_finddevice("/");
  974         if (root == -1) {
  975                 device_printf(dev, "failed to get FDT root node\n");
  976                 return (ENXIO);
  977         }
  978 
  979         /* Fixme: Cant find any reference in DTS for dpll_disp_ck@498 for now. */
  980         err = clk_get_by_name(dev, "dpll_disp_ck@498", &sc->sc_clk_dpll_disp_ck);
  981         if (err != 0) {
  982                 device_printf(dev, "Cant get dpll_disp_ck@49\n");
  983                 return (ENXIO);
  984         }
  985 
  986         sc->sc_panel.ac_bias = 255;
  987         sc->sc_panel.ac_bias_intrpt = 0;
  988         sc->sc_panel.dma_burst_sz = 16;
  989         sc->sc_panel.bpp = 16;
  990         sc->sc_panel.fdd = 128;
  991         sc->sc_panel.sync_edge = 0;
  992         sc->sc_panel.sync_ctrl = 1;
  993 
  994         panel_node = fdt_find_compatible(root, "ti,tilcdc,panel", 1);
  995         if (panel_node != 0) {
  996                 device_printf(dev, "using static panel info\n");
  997                 if (am335x_read_panel_info(dev, panel_node, &sc->sc_panel)) {
  998                         device_printf(dev, "failed to read panel info\n");
  999                         return (ENXIO);
 1000                 }
 1001 
 1002                 if (am335x_read_timing(dev, panel_node, &sc->sc_panel)) {
 1003                         device_printf(dev, "failed to read timings\n");
 1004                         return (ENXIO);
 1005                 }
 1006         }
 1007 
 1008         err = ti_sysc_clock_enable(device_get_parent(dev));
 1009         if (err != 0) {
 1010                 device_printf(dev, "Failed to enable sysc clkctrl, err %d\n", err);
 1011                 return (ENXIO);
 1012         }
 1013 
 1014         rid = 0;
 1015         sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
 1016             RF_ACTIVE);
 1017         if (!sc->sc_mem_res) {
 1018                 device_printf(dev, "cannot allocate memory window\n");
 1019                 return (ENXIO);
 1020         }
 1021 
 1022         rid = 0;
 1023         sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
 1024             RF_ACTIVE);
 1025         if (!sc->sc_irq_res) {
 1026                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
 1027                 device_printf(dev, "cannot allocate interrupt\n");
 1028                 return (ENXIO);
 1029         }
 1030 
 1031         if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
 1032                         NULL, am335x_lcd_intr, sc,
 1033                         &sc->sc_intr_hl) != 0) {
 1034                 bus_release_resource(dev, SYS_RES_IRQ, rid,
 1035                     sc->sc_irq_res);
 1036                 bus_release_resource(dev, SYS_RES_MEMORY, rid,
 1037                     sc->sc_mem_res);
 1038                 device_printf(dev, "Unable to setup the irq handler.\n");
 1039                 return (ENXIO);
 1040         }
 1041 
 1042         LCD_LOCK_INIT(sc);
 1043 
 1044         /* Init backlight interface */
 1045         ctx = device_get_sysctl_ctx(sc->sc_dev);
 1046         tree = device_get_sysctl_tree(sc->sc_dev);
 1047         sc->sc_oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
 1048             "backlight", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0,
 1049             am335x_lcd_sysctl_backlight, "I", "LCD backlight");
 1050         sc->sc_backlight = 0;
 1051         /* Check if eCAS interface is available at this point */
 1052         if (am335x_pwm_config_ecap(PWM_UNIT,
 1053             PWM_PERIOD, PWM_PERIOD) == 0)
 1054                 sc->sc_backlight = 100;
 1055 
 1056         if (panel_node != 0)
 1057                 am335x_lcd_configure(sc);
 1058         else
 1059                 sc->sc_hdmi_evh = EVENTHANDLER_REGISTER(hdmi_event,
 1060                     am335x_lcd_hdmi_event, sc, EVENTHANDLER_PRI_ANY);
 1061 
 1062         return (0);
 1063 }
 1064 
 1065 static int
 1066 am335x_lcd_detach(device_t dev)
 1067 {
 1068         /* Do not let unload driver */
 1069         return (EBUSY);
 1070 }
 1071 
 1072 static struct fb_info *
 1073 am335x_lcd_fb_getinfo(device_t dev)
 1074 {
 1075         struct am335x_lcd_softc *sc;
 1076 
 1077         sc = device_get_softc(dev);
 1078 
 1079         return (&sc->sc_fb_info);
 1080 }
 1081 
 1082 static device_method_t am335x_lcd_methods[] = {
 1083         DEVMETHOD(device_probe,         am335x_lcd_probe),
 1084         DEVMETHOD(device_attach,        am335x_lcd_attach),
 1085         DEVMETHOD(device_detach,        am335x_lcd_detach),
 1086 
 1087         /* Framebuffer service methods */
 1088         DEVMETHOD(fb_getinfo,           am335x_lcd_fb_getinfo),
 1089 
 1090         DEVMETHOD_END
 1091 };
 1092 
 1093 static driver_t am335x_lcd_driver = {
 1094         "fb",
 1095         am335x_lcd_methods,
 1096         sizeof(struct am335x_lcd_softc),
 1097 };
 1098 
 1099 DRIVER_MODULE(am335x_lcd, simplebus, am335x_lcd_driver, 0, 0);
 1100 MODULE_VERSION(am335x_lcd, 1);
 1101 MODULE_DEPEND(am335x_lcd, simplebus, 1, 1, 1);
 1102 MODULE_DEPEND(am335x_lcd, ti_sysc, 1, 1, 1);

Cache object: 13199b18416fd442963b4f871beee761


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.