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