1 /*-
2 * Copyright 2013 Oleksandr Tymoshenko <gonzo@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD: stable/10/sys/arm/ti/am335x/am335x_lcd.c 266152 2014-05-15 16:11:06Z ian $");
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/module.h>
34 #include <sys/clock.h>
35 #include <sys/time.h>
36 #include <sys/bus.h>
37 #include <sys/lock.h>
38 #include <sys/mutex.h>
39 #include <sys/resource.h>
40 #include <sys/rman.h>
41 #include <sys/sysctl.h>
42 #include <vm/vm.h>
43 #include <vm/pmap.h>
44
45 /* syscons bits */
46 #include <sys/fbio.h>
47 #include <sys/consio.h>
48
49 #include <machine/bus.h>
50
51 #include <dev/fdt/fdt_common.h>
52 #include <dev/ofw/openfirm.h>
53 #include <dev/ofw/ofw_bus.h>
54 #include <dev/ofw/ofw_bus_subr.h>
55
56 #include <dev/fb/fbreg.h>
57 #include <dev/syscons/syscons.h>
58
59 #include <arm/ti/ti_prcm.h>
60 #include <arm/ti/ti_scm.h>
61
62 #include "am335x_lcd.h"
63 #include "am335x_pwm.h"
64
65 #define LCD_PID 0x00
66 #define LCD_CTRL 0x04
67 #define CTRL_DIV_MASK 0xff
68 #define CTRL_DIV_SHIFT 8
69 #define CTRL_AUTO_UFLOW_RESTART (1 << 1)
70 #define CTRL_RASTER_MODE 1
71 #define CTRL_LIDD_MODE 0
72 #define LCD_LIDD_CTRL 0x0C
73 #define LCD_LIDD_CS0_CONF 0x10
74 #define LCD_LIDD_CS0_ADDR 0x14
75 #define LCD_LIDD_CS0_DATA 0x18
76 #define LCD_LIDD_CS1_CONF 0x1C
77 #define LCD_LIDD_CS1_ADDR 0x20
78 #define LCD_LIDD_CS1_DATA 0x24
79 #define LCD_RASTER_CTRL 0x28
80 #define RASTER_CTRL_TFT24_UNPACKED (1 << 26)
81 #define RASTER_CTRL_TFT24 (1 << 25)
82 #define RASTER_CTRL_STN565 (1 << 24)
83 #define RASTER_CTRL_TFTPMAP (1 << 23)
84 #define RASTER_CTRL_NIBMODE (1 << 22)
85 #define RASTER_CTRL_PALMODE_SHIFT 20
86 #define PALETTE_PALETTE_AND_DATA 0x00
87 #define PALETTE_PALETTE_ONLY 0x01
88 #define PALETTE_DATA_ONLY 0x02
89 #define RASTER_CTRL_REQDLY_SHIFT 12
90 #define RASTER_CTRL_MONO8B (1 << 9)
91 #define RASTER_CTRL_RBORDER (1 << 8)
92 #define RASTER_CTRL_LCDTFT (1 << 7)
93 #define RASTER_CTRL_LCDBW (1 << 1)
94 #define RASTER_CTRL_LCDEN (1 << 0)
95 #define LCD_RASTER_TIMING_0 0x2C
96 #define RASTER_TIMING_0_HBP_SHIFT 24
97 #define RASTER_TIMING_0_HFP_SHIFT 16
98 #define RASTER_TIMING_0_HSW_SHIFT 10
99 #define RASTER_TIMING_0_PPLLSB_SHIFT 4
100 #define RASTER_TIMING_0_PPLMSB_SHIFT 3
101 #define LCD_RASTER_TIMING_1 0x30
102 #define RASTER_TIMING_1_VBP_SHIFT 24
103 #define RASTER_TIMING_1_VFP_SHIFT 16
104 #define RASTER_TIMING_1_VSW_SHIFT 10
105 #define RASTER_TIMING_1_LPP_SHIFT 0
106 #define LCD_RASTER_TIMING_2 0x34
107 #define RASTER_TIMING_2_HSWHI_SHIFT 27
108 #define RASTER_TIMING_2_LPP_B10_SHIFT 26
109 #define RASTER_TIMING_2_PHSVS (1 << 25)
110 #define RASTER_TIMING_2_PHSVS_RISE (1 << 24)
111 #define RASTER_TIMING_2_PHSVS_FALL (0 << 24)
112 #define RASTER_TIMING_2_IOE (1 << 23)
113 #define RASTER_TIMING_2_IPC (1 << 22)
114 #define RASTER_TIMING_2_IHS (1 << 21)
115 #define RASTER_TIMING_2_IVS (1 << 20)
116 #define RASTER_TIMING_2_ACBI_SHIFT 16
117 #define RASTER_TIMING_2_ACB_SHIFT 8
118 #define RASTER_TIMING_2_HBPHI_SHIFT 4
119 #define RASTER_TIMING_2_HFPHI_SHIFT 0
120 #define LCD_RASTER_SUBPANEL 0x38
121 #define LCD_RASTER_SUBPANEL2 0x3C
122 #define LCD_LCDDMA_CTRL 0x40
123 #define LCDDMA_CTRL_DMA_MASTER_PRIO_SHIFT 16
124 #define LCDDMA_CTRL_TH_FIFO_RDY_SHIFT 8
125 #define LCDDMA_CTRL_BURST_SIZE_SHIFT 4
126 #define LCDDMA_CTRL_BYTES_SWAP (1 << 3)
127 #define LCDDMA_CTRL_BE (1 << 1)
128 #define LCDDMA_CTRL_FB0_ONLY 0
129 #define LCDDMA_CTRL_FB0_FB1 (1 << 0)
130 #define LCD_LCDDMA_FB0_BASE 0x44
131 #define LCD_LCDDMA_FB0_CEILING 0x48
132 #define LCD_LCDDMA_FB1_BASE 0x4C
133 #define LCD_LCDDMA_FB1_CEILING 0x50
134 #define LCD_SYSCONFIG 0x54
135 #define SYSCONFIG_STANDBY_FORCE (0 << 4)
136 #define SYSCONFIG_STANDBY_NONE (1 << 4)
137 #define SYSCONFIG_STANDBY_SMART (2 << 4)
138 #define SYSCONFIG_IDLE_FORCE (0 << 2)
139 #define SYSCONFIG_IDLE_NONE (1 << 2)
140 #define SYSCONFIG_IDLE_SMART (2 << 2)
141 #define LCD_IRQSTATUS_RAW 0x58
142 #define LCD_IRQSTATUS 0x5C
143 #define LCD_IRQENABLE_SET 0x60
144 #define LCD_IRQENABLE_CLEAR 0x64
145 #define IRQ_EOF1 (1 << 9)
146 #define IRQ_EOF0 (1 << 8)
147 #define IRQ_PL (1 << 6)
148 #define IRQ_FUF (1 << 5)
149 #define IRQ_ACB (1 << 3)
150 #define IRQ_SYNC_LOST (1 << 2)
151 #define IRQ_RASTER_DONE (1 << 1)
152 #define IRQ_FRAME_DONE (1 << 0)
153 #define LCD_CLKC_ENABLE 0x6C
154 #define CLKC_ENABLE_DMA (1 << 2)
155 #define CLKC_ENABLE_LDID (1 << 1)
156 #define CLKC_ENABLE_CORE (1 << 0)
157 #define LCD_CLKC_RESET 0x70
158 #define CLKC_RESET_MAIN (1 << 3)
159 #define CLKC_RESET_DMA (1 << 2)
160 #define CLKC_RESET_LDID (1 << 1)
161 #define CLKC_RESET_CORE (1 << 0)
162
163 #define LCD_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
164 #define LCD_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
165 #define LCD_LOCK_INIT(_sc) mtx_init(&(_sc)->sc_mtx, \
166 device_get_nameunit(_sc->sc_dev), "am335x_lcd", MTX_DEF)
167 #define LCD_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx);
168
169 #define LCD_READ4(_sc, reg) bus_read_4((_sc)->sc_mem_res, reg);
170 #define LCD_WRITE4(_sc, reg, value) \
171 bus_write_4((_sc)->sc_mem_res, reg, value);
172
173
174 /* Backlight is controlled by eCAS interface on PWM unit 0 */
175 #define PWM_UNIT 0
176 #define PWM_PERIOD 100
177
178 struct am335x_lcd_softc {
179 device_t sc_dev;
180 struct resource *sc_mem_res;
181 struct resource *sc_irq_res;
182 void *sc_intr_hl;
183 struct mtx sc_mtx;
184 int sc_backlight;
185 struct sysctl_oid *sc_oid;
186
187 /* Framebuffer */
188 bus_dma_tag_t sc_dma_tag;
189 bus_dmamap_t sc_dma_map;
190 size_t sc_fb_size;
191 bus_addr_t sc_fb_phys;
192 uint8_t *sc_fb_base;
193 };
194
195 static void
am335x_fb_dmamap_cb(void * arg,bus_dma_segment_t * segs,int nseg,int err)196 am335x_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
197 {
198 bus_addr_t *addr;
199
200 if (err)
201 return;
202
203 addr = (bus_addr_t*)arg;
204 *addr = segs[0].ds_addr;
205 }
206
207 static uint32_t
am335x_lcd_calc_divisor(uint32_t reference,uint32_t freq)208 am335x_lcd_calc_divisor(uint32_t reference, uint32_t freq)
209 {
210 uint32_t div;
211 /* Raster mode case: divisors are in range from 2 to 255 */
212 for (div = 2; div < 255; div++)
213 if (reference/div <= freq)
214 return (div);
215
216 return (255);
217 }
218
219 static int
am335x_lcd_sysctl_backlight(SYSCTL_HANDLER_ARGS)220 am335x_lcd_sysctl_backlight(SYSCTL_HANDLER_ARGS)
221 {
222 struct am335x_lcd_softc *sc = (struct am335x_lcd_softc*)arg1;
223 int error;
224 int backlight;
225
226 backlight = sc->sc_backlight;;
227 error = sysctl_handle_int(oidp, &backlight, 0, req);
228
229 if (error != 0 || req->newptr == NULL)
230 return (error);
231
232 if (backlight < 0)
233 backlight = 0;
234 if (backlight > 100)
235 backlight = 100;
236
237 LCD_LOCK(sc);
238 error = am335x_pwm_config_ecas(PWM_UNIT, PWM_PERIOD,
239 backlight*PWM_PERIOD/100);
240 if (error == 0)
241 sc->sc_backlight = backlight;
242 LCD_UNLOCK(sc);
243
244 return (error);
245 }
246
247 static int
am335x_read_panel_property(device_t dev,const char * name,uint32_t * val)248 am335x_read_panel_property(device_t dev, const char *name, uint32_t *val)
249 {
250 phandle_t node;
251 pcell_t cell;
252
253 node = ofw_bus_get_node(dev);
254 if ((OF_getprop(node, name, &cell, sizeof(cell))) <= 0) {
255 device_printf(dev, "missing '%s' attribute in LCD panel info\n",
256 name);
257 return (ENXIO);
258 }
259
260 *val = fdt32_to_cpu(cell);
261
262 return (0);
263 }
264
265 static int
am335x_read_panel_info(device_t dev,struct panel_info * panel)266 am335x_read_panel_info(device_t dev, struct panel_info *panel)
267 {
268 int error;
269
270 error = 0;
271 if ((error = am335x_read_panel_property(dev,
272 "panel_width", &panel->panel_width)))
273 goto out;
274
275 if ((error = am335x_read_panel_property(dev,
276 "panel_height", &panel->panel_height)))
277 goto out;
278
279 if ((error = am335x_read_panel_property(dev,
280 "panel_hfp", &panel->panel_hfp)))
281 goto out;
282
283 if ((error = am335x_read_panel_property(dev,
284 "panel_hbp", &panel->panel_hbp)))
285 goto out;
286
287 if ((error = am335x_read_panel_property(dev,
288 "panel_hsw", &panel->panel_hsw)))
289 goto out;
290
291 if ((error = am335x_read_panel_property(dev,
292 "panel_vfp", &panel->panel_vfp)))
293 goto out;
294
295 if ((error = am335x_read_panel_property(dev,
296 "panel_vbp", &panel->panel_vbp)))
297 goto out;
298
299 if ((error = am335x_read_panel_property(dev,
300 "panel_vsw", &panel->panel_vsw)))
301 goto out;
302
303 if ((error = am335x_read_panel_property(dev,
304 "panel_pxl_clk", &panel->panel_pxl_clk)))
305 goto out;
306
307 if ((error = am335x_read_panel_property(dev,
308 "panel_invert_pxl_clk", &panel->panel_invert_pxl_clk)))
309 goto out;
310
311 if ((error = am335x_read_panel_property(dev,
312 "ac_bias", &panel->ac_bias)))
313 goto out;
314
315 if ((error = am335x_read_panel_property(dev,
316 "ac_bias_intrpt", &panel->ac_bias_intrpt)))
317 goto out;
318
319 if ((error = am335x_read_panel_property(dev,
320 "dma_burst_sz", &panel->dma_burst_sz)))
321 goto out;
322
323 if ((error = am335x_read_panel_property(dev,
324 "bpp", &panel->bpp)))
325 goto out;
326
327 if ((error = am335x_read_panel_property(dev,
328 "fdd", &panel->fdd)))
329 goto out;
330
331 if ((error = am335x_read_panel_property(dev,
332 "invert_line_clock", &panel->invert_line_clock)))
333 goto out;
334
335 if ((error = am335x_read_panel_property(dev,
336 "invert_frm_clock", &panel->invert_frm_clock)))
337 goto out;
338
339 if ((error = am335x_read_panel_property(dev,
340 "sync_edge", &panel->sync_edge)))
341 goto out;
342
343 error = am335x_read_panel_property(dev,
344 "sync_ctrl", &panel->sync_ctrl);
345
346 out:
347 return (error);
348 }
349
350 static void
am335x_lcd_intr(void * arg)351 am335x_lcd_intr(void *arg)
352 {
353 struct am335x_lcd_softc *sc = arg;
354 uint32_t reg;
355
356 reg = LCD_READ4(sc, LCD_IRQSTATUS);
357 LCD_WRITE4(sc, LCD_IRQSTATUS, reg);
358
359 if (reg & IRQ_SYNC_LOST) {
360 reg = LCD_READ4(sc, LCD_RASTER_CTRL);
361 reg &= ~RASTER_CTRL_LCDEN;
362 LCD_WRITE4(sc, LCD_RASTER_CTRL, reg);
363
364 reg = LCD_READ4(sc, LCD_RASTER_CTRL);
365 reg |= RASTER_CTRL_LCDEN;
366 LCD_WRITE4(sc, LCD_RASTER_CTRL, reg);
367 return;
368 }
369
370 if (reg & IRQ_PL) {
371 reg = LCD_READ4(sc, LCD_RASTER_CTRL);
372 reg &= ~RASTER_CTRL_LCDEN;
373 LCD_WRITE4(sc, LCD_RASTER_CTRL, reg);
374
375 reg = LCD_READ4(sc, LCD_RASTER_CTRL);
376 reg |= RASTER_CTRL_LCDEN;
377 LCD_WRITE4(sc, LCD_RASTER_CTRL, reg);
378 return;
379 }
380
381 if (reg & IRQ_EOF0) {
382 LCD_WRITE4(sc, LCD_LCDDMA_FB0_BASE, sc->sc_fb_phys);
383 LCD_WRITE4(sc, LCD_LCDDMA_FB0_CEILING, sc->sc_fb_phys + sc->sc_fb_size - 1);
384 reg &= ~IRQ_EOF0;
385 }
386
387 if (reg & IRQ_EOF1) {
388 LCD_WRITE4(sc, LCD_LCDDMA_FB1_BASE, sc->sc_fb_phys);
389 LCD_WRITE4(sc, LCD_LCDDMA_FB1_CEILING, sc->sc_fb_phys + sc->sc_fb_size - 1);
390 reg &= ~IRQ_EOF1;
391 }
392
393 if (reg & IRQ_FUF) {
394 /* TODO: Handle FUF */
395 }
396
397 if (reg & IRQ_ACB) {
398 /* TODO: Handle ACB */
399 }
400 }
401
402 static int
am335x_lcd_probe(device_t dev)403 am335x_lcd_probe(device_t dev)
404 {
405 int err;
406
407 if (!ofw_bus_status_okay(dev))
408 return (ENXIO);
409
410 if (!ofw_bus_is_compatible(dev, "ti,am335x-lcd"))
411 return (ENXIO);
412
413 device_set_desc(dev, "AM335x LCD controller");
414
415 err = sc_probe_unit(device_get_unit(dev),
416 device_get_flags(dev) | SC_AUTODETECT_KBD);
417 if (err != 0)
418 return (err);
419
420 return (BUS_PROBE_DEFAULT);
421 }
422
423 static int
am335x_lcd_attach(device_t dev)424 am335x_lcd_attach(device_t dev)
425 {
426 struct am335x_lcd_softc *sc;
427 int rid;
428 int div;
429 struct panel_info panel;
430 uint32_t reg, timing0, timing1, timing2;
431 struct sysctl_ctx_list *ctx;
432 struct sysctl_oid *tree;
433 uint32_t burst_log;
434 int err;
435 size_t dma_size;
436
437 sc = device_get_softc(dev);
438 sc->sc_dev = dev;
439
440 if (am335x_read_panel_info(dev, &panel))
441 return (ENXIO);
442
443 int ref_freq = 0;
444 ti_prcm_clk_enable(LCDC_CLK);
445 if (ti_prcm_clk_get_source_freq(LCDC_CLK, &ref_freq)) {
446 device_printf(dev, "Can't get reference frequency\n");
447 return (ENXIO);
448 }
449
450 rid = 0;
451 sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
452 RF_ACTIVE);
453 if (!sc->sc_mem_res) {
454 device_printf(dev, "cannot allocate memory window\n");
455 return (ENXIO);
456 }
457
458 rid = 0;
459 sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
460 RF_ACTIVE);
461 if (!sc->sc_irq_res) {
462 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
463 device_printf(dev, "cannot allocate interrupt\n");
464 return (ENXIO);
465 }
466
467 if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
468 NULL, am335x_lcd_intr, sc,
469 &sc->sc_intr_hl) != 0) {
470 bus_release_resource(dev, SYS_RES_IRQ, rid,
471 sc->sc_irq_res);
472 bus_release_resource(dev, SYS_RES_MEMORY, rid,
473 sc->sc_mem_res);
474 device_printf(dev, "Unable to setup the irq handler.\n");
475 return (ENXIO);
476 }
477
478 LCD_LOCK_INIT(sc);
479
480 /* Panle initialization */
481 dma_size = round_page(panel.panel_width*panel.panel_height*panel.bpp/8);
482
483 /*
484 * Now allocate framebuffer memory
485 */
486 err = bus_dma_tag_create(
487 bus_get_dma_tag(dev),
488 4, 0, /* alignment, boundary */
489 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
490 BUS_SPACE_MAXADDR, /* highaddr */
491 NULL, NULL, /* filter, filterarg */
492 dma_size, 1, /* maxsize, nsegments */
493 dma_size, 0, /* maxsegsize, flags */
494 NULL, NULL, /* lockfunc, lockarg */
495 &sc->sc_dma_tag);
496 if (err)
497 goto fail;
498
499 err = bus_dmamem_alloc(sc->sc_dma_tag, (void **)&sc->sc_fb_base,
500 BUS_DMA_COHERENT, &sc->sc_dma_map);
501
502 if (err) {
503 device_printf(dev, "cannot allocate framebuffer\n");
504 goto fail;
505 }
506
507 err = bus_dmamap_load(sc->sc_dma_tag, sc->sc_dma_map, sc->sc_fb_base,
508 dma_size, am335x_fb_dmamap_cb, &sc->sc_fb_phys, BUS_DMA_NOWAIT);
509
510 if (err) {
511 device_printf(dev, "cannot load DMA map\n");
512 goto fail;
513 }
514
515 /* Make sure it's blank */
516 memset(sc->sc_fb_base, 0x00, dma_size);
517
518 /* Calculate actual FB Size */
519 sc->sc_fb_size = panel.panel_width*panel.panel_height*panel.bpp/8;
520
521 /* Only raster mode is supported */
522 reg = CTRL_RASTER_MODE;
523 div = am335x_lcd_calc_divisor(ref_freq, panel.panel_pxl_clk);
524 reg |= (div << CTRL_DIV_SHIFT);
525 LCD_WRITE4(sc, LCD_CTRL, reg);
526
527 /* Set timing */
528 timing0 = timing1 = timing2 = 0;
529
530 /* Horizontal back porch */
531 timing0 |= (panel.panel_hbp & 0xff) << RASTER_TIMING_0_HBP_SHIFT;
532 timing2 |= ((panel.panel_hbp >> 8) & 3) << RASTER_TIMING_2_HBPHI_SHIFT;
533 /* Horizontal front porch */
534 timing0 |= (panel.panel_hfp & 0xff) << RASTER_TIMING_0_HFP_SHIFT;
535 timing2 |= ((panel.panel_hfp >> 8) & 3) << RASTER_TIMING_2_HFPHI_SHIFT;
536 /* Horizontal sync width */
537 timing0 |= (panel.panel_hsw & 0x3f) << RASTER_TIMING_0_HSW_SHIFT;
538 timing2 |= ((panel.panel_hsw >> 6) & 0xf) << RASTER_TIMING_2_HSWHI_SHIFT;
539
540 /* Vertical back porch, front porch, sync width */
541 timing1 |= (panel.panel_vbp & 0xff) << RASTER_TIMING_1_VBP_SHIFT;
542 timing1 |= (panel.panel_vfp & 0xff) << RASTER_TIMING_1_VFP_SHIFT;
543 timing1 |= (panel.panel_vsw & 0x3f) << RASTER_TIMING_1_VSW_SHIFT;
544
545 /* Pixels per line */
546 timing0 |= (((panel.panel_width - 1) >> 10) & 1)
547 << RASTER_TIMING_0_PPLMSB_SHIFT;
548 timing0 |= (((panel.panel_width - 1) >> 4) & 0x3f)
549 << RASTER_TIMING_0_PPLLSB_SHIFT;
550
551 /* Lines per panel */
552 timing1 |= ((panel.panel_height - 1) & 0x3ff)
553 << RASTER_TIMING_1_LPP_SHIFT;
554 timing2 |= (((panel.panel_height - 1) >> 10 ) & 1)
555 << RASTER_TIMING_2_LPP_B10_SHIFT;
556
557 /* clock signal settings */
558 if (panel.sync_ctrl)
559 timing2 |= RASTER_TIMING_2_PHSVS;
560 if (panel.sync_edge)
561 timing2 |= RASTER_TIMING_2_PHSVS_RISE;
562 else
563 timing2 |= RASTER_TIMING_2_PHSVS_FALL;
564 if (panel.invert_line_clock)
565 timing2 |= RASTER_TIMING_2_IHS;
566 if (panel.invert_frm_clock)
567 timing2 |= RASTER_TIMING_2_IVS;
568 if (panel.panel_invert_pxl_clk)
569 timing2 |= RASTER_TIMING_2_IPC;
570
571 /* AC bias */
572 timing2 |= (panel.ac_bias << RASTER_TIMING_2_ACB_SHIFT);
573 timing2 |= (panel.ac_bias_intrpt << RASTER_TIMING_2_ACBI_SHIFT);
574
575 LCD_WRITE4(sc, LCD_RASTER_TIMING_0, timing0);
576 LCD_WRITE4(sc, LCD_RASTER_TIMING_1, timing1);
577 LCD_WRITE4(sc, LCD_RASTER_TIMING_2, timing2);
578
579 /* DMA settings */
580 reg = LCDDMA_CTRL_FB0_FB1;
581 /* Find power of 2 for current burst size */
582 switch (panel.dma_burst_sz) {
583 case 1:
584 burst_log = 0;
585 break;
586 case 2:
587 burst_log = 1;
588 break;
589 case 4:
590 burst_log = 2;
591 break;
592 case 8:
593 burst_log = 3;
594 break;
595 case 16:
596 default:
597 burst_log = 4;
598 break;
599 }
600 reg |= (burst_log << LCDDMA_CTRL_BURST_SIZE_SHIFT);
601 /* XXX: FIFO TH */
602 reg |= (0 << LCDDMA_CTRL_TH_FIFO_RDY_SHIFT);
603 LCD_WRITE4(sc, LCD_LCDDMA_CTRL, reg);
604
605 LCD_WRITE4(sc, LCD_LCDDMA_FB0_BASE, sc->sc_fb_phys);
606 LCD_WRITE4(sc, LCD_LCDDMA_FB0_CEILING, sc->sc_fb_phys + sc->sc_fb_size - 1);
607 LCD_WRITE4(sc, LCD_LCDDMA_FB1_BASE, sc->sc_fb_phys);
608 LCD_WRITE4(sc, LCD_LCDDMA_FB1_CEILING, sc->sc_fb_phys + sc->sc_fb_size - 1);
609
610 /* Enable LCD */
611 reg = RASTER_CTRL_LCDTFT;
612 reg |= (panel.fdd << RASTER_CTRL_REQDLY_SHIFT);
613 reg |= (PALETTE_DATA_ONLY << RASTER_CTRL_PALMODE_SHIFT);
614 if (panel.bpp >= 24)
615 reg |= RASTER_CTRL_TFT24;
616 if (panel.bpp == 32)
617 reg |= RASTER_CTRL_TFT24_UNPACKED;
618 LCD_WRITE4(sc, LCD_RASTER_CTRL, reg);
619
620 LCD_WRITE4(sc, LCD_CLKC_ENABLE,
621 CLKC_ENABLE_DMA | CLKC_ENABLE_LDID | CLKC_ENABLE_CORE);
622
623 LCD_WRITE4(sc, LCD_CLKC_RESET, CLKC_RESET_MAIN);
624 DELAY(100);
625 LCD_WRITE4(sc, LCD_CLKC_RESET, 0);
626
627 reg = IRQ_EOF1 | IRQ_EOF0 | IRQ_FUF | IRQ_PL |
628 IRQ_ACB | IRQ_SYNC_LOST | IRQ_RASTER_DONE |
629 IRQ_FRAME_DONE;
630 LCD_WRITE4(sc, LCD_IRQENABLE_SET, reg);
631
632 reg = LCD_READ4(sc, LCD_RASTER_CTRL);
633 reg |= RASTER_CTRL_LCDEN;
634 LCD_WRITE4(sc, LCD_RASTER_CTRL, reg);
635
636 LCD_WRITE4(sc, LCD_SYSCONFIG,
637 SYSCONFIG_STANDBY_SMART | SYSCONFIG_IDLE_SMART);
638
639 /* Init backlight interface */
640 ctx = device_get_sysctl_ctx(sc->sc_dev);
641 tree = device_get_sysctl_tree(sc->sc_dev);
642 sc->sc_oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
643 "backlight", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
644 am335x_lcd_sysctl_backlight, "I", "LCD backlight");
645 sc->sc_backlight = 0;
646 /* Check if eCAS interface is available at this point */
647 if (am335x_pwm_config_ecas(PWM_UNIT,
648 PWM_PERIOD, PWM_PERIOD) == 0)
649 sc->sc_backlight = 100;
650
651 err = (sc_attach_unit(device_get_unit(dev),
652 device_get_flags(dev) | SC_AUTODETECT_KBD));
653
654 if (err) {
655 device_printf(dev, "failed to attach syscons\n");
656 goto fail;
657 }
658
659 am335x_lcd_syscons_setup((vm_offset_t)sc->sc_fb_base, sc->sc_fb_phys, &panel);
660
661 return (0);
662
663 fail:
664 return (err);
665 }
666
667 static int
am335x_lcd_detach(device_t dev)668 am335x_lcd_detach(device_t dev)
669 {
670 /* Do not let unload driver */
671 return (EBUSY);
672 }
673
674 static device_method_t am335x_lcd_methods[] = {
675 DEVMETHOD(device_probe, am335x_lcd_probe),
676 DEVMETHOD(device_attach, am335x_lcd_attach),
677 DEVMETHOD(device_detach, am335x_lcd_detach),
678
679 DEVMETHOD_END
680 };
681
682 static driver_t am335x_lcd_driver = {
683 "am335x_lcd",
684 am335x_lcd_methods,
685 sizeof(struct am335x_lcd_softc),
686 };
687
688 static devclass_t am335x_lcd_devclass;
689
690 DRIVER_MODULE(am335x_lcd, simplebus, am335x_lcd_driver, am335x_lcd_devclass, 0, 0);
691 MODULE_VERSION(am335x_lcd, 1);
692 MODULE_DEPEND(am335x_lcd, simplebus, 1, 1, 1);
693