Deleted Added
full compact
vf_dcu4.c (266155) vf_dcu4.c (266274)
1/*-
2 * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
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

--- 16 unchanged lines hidden (view full) ---

25 */
26
27/*
28 * Vybrid Family Display Control Unit (DCU4)
29 * Chapter 55, Vybrid Reference Manual, Rev. 5, 07/2013
30 */
31
32#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
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

--- 16 unchanged lines hidden (view full) ---

25 */
26
27/*
28 * Vybrid Family Display Control Unit (DCU4)
29 * Chapter 55, Vybrid Reference Manual, Rev. 5, 07/2013
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_dcu4.c 266155 2014-05-15 16:23:24Z ian $");
33__FBSDID("$FreeBSD: stable/10/sys/arm/freescale/vybrid/vf_dcu4.c 266274 2014-05-16 23:27:18Z ian $");
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/bus.h>
38#include <sys/kernel.h>
39#include <sys/module.h>
40#include <sys/malloc.h>
41#include <sys/rman.h>
42#include <sys/timeet.h>
43#include <sys/timetc.h>
44#include <sys/watchdog.h>
45#include <sys/fbio.h>
46#include <sys/consio.h>
47#include <sys/eventhandler.h>
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/bus.h>
38#include <sys/kernel.h>
39#include <sys/module.h>
40#include <sys/malloc.h>
41#include <sys/rman.h>
42#include <sys/timeet.h>
43#include <sys/timetc.h>
44#include <sys/watchdog.h>
45#include <sys/fbio.h>
46#include <sys/consio.h>
47#include <sys/eventhandler.h>
48#include <sys/gpio.h>
48
49#include <dev/fdt/fdt_common.h>
50#include <dev/ofw/openfirm.h>
51#include <dev/ofw/ofw_bus.h>
52#include <dev/ofw/ofw_bus_subr.h>
53
54#include <dev/vt/vt.h>
55#include <dev/vt/colors/vt_termcolors.h>
56
49
50#include <dev/fdt/fdt_common.h>
51#include <dev/ofw/openfirm.h>
52#include <dev/ofw/ofw_bus.h>
53#include <dev/ofw/ofw_bus_subr.h>
54
55#include <dev/vt/vt.h>
56#include <dev/vt/colors/vt_termcolors.h>
57
58#include "gpio_if.h"
59
57#include <machine/bus.h>
58#include <machine/fdt.h>
59#include <machine/cpu.h>
60#include <machine/intr.h>
61
62#include "fb_if.h"
63
64#include <arm/freescale/vybrid/vf_common.h>

--- 4 unchanged lines hidden (view full) ---

69#define DCU_CTRLDESCCURSOR4 0x00C /* Control Descriptor Cursor 4 */
70#define DCU_DCU_MODE 0x010 /* DCU4 Mode */
71#define DCU_MODE_M 0x3
72#define DCU_MODE_S 0
73#define DCU_MODE_NORMAL 0x1
74#define DCU_MODE_TEST 0x2
75#define DCU_MODE_COLBAR 0x3
76#define RASTER_EN (1 << 14) /* Raster scan of pixel data */
60#include <machine/bus.h>
61#include <machine/fdt.h>
62#include <machine/cpu.h>
63#include <machine/intr.h>
64
65#include "fb_if.h"
66
67#include <arm/freescale/vybrid/vf_common.h>

--- 4 unchanged lines hidden (view full) ---

72#define DCU_CTRLDESCCURSOR4 0x00C /* Control Descriptor Cursor 4 */
73#define DCU_DCU_MODE 0x010 /* DCU4 Mode */
74#define DCU_MODE_M 0x3
75#define DCU_MODE_S 0
76#define DCU_MODE_NORMAL 0x1
77#define DCU_MODE_TEST 0x2
78#define DCU_MODE_COLBAR 0x3
79#define RASTER_EN (1 << 14) /* Raster scan of pixel data */
80#define PDI_EN (1 << 13)
81#define PDI_DE_MODE (1 << 11)
82#define PDI_MODE_M 2
77#define DCU_BGND 0x014 /* Background */
78#define DCU_DISP_SIZE 0x018 /* Display Size */
79#define DELTA_M 0x7ff
80#define DELTA_Y_S 16
81#define DELTA_X_S 0
82#define DCU_HSYN_PARA 0x01C /* Horizontal Sync Parameter */
83#define BP_H_SHIFT 22
84#define PW_H_SHIFT 11
85#define FP_H_SHIFT 0
86#define DCU_VSYN_PARA 0x020 /* Vertical Sync Parameter */
87#define BP_V_SHIFT 22
88#define PW_V_SHIFT 11
89#define FP_V_SHIFT 0
90#define DCU_SYNPOL 0x024 /* Synchronize Polarity */
91#define INV_HS (1 << 0)
92#define INV_VS (1 << 1)
83#define DCU_BGND 0x014 /* Background */
84#define DCU_DISP_SIZE 0x018 /* Display Size */
85#define DELTA_M 0x7ff
86#define DELTA_Y_S 16
87#define DELTA_X_S 0
88#define DCU_HSYN_PARA 0x01C /* Horizontal Sync Parameter */
89#define BP_H_SHIFT 22
90#define PW_H_SHIFT 11
91#define FP_H_SHIFT 0
92#define DCU_VSYN_PARA 0x020 /* Vertical Sync Parameter */
93#define BP_V_SHIFT 22
94#define PW_V_SHIFT 11
95#define FP_V_SHIFT 0
96#define DCU_SYNPOL 0x024 /* Synchronize Polarity */
97#define INV_HS (1 << 0)
98#define INV_VS (1 << 1)
99#define INV_PDI_VS (1 << 8) /* Polarity of PDI input VSYNC. */
100#define INV_PDI_HS (1 << 9) /* Polarity of PDI input HSYNC. */
101#define INV_PDI_DE (1 << 10) /* Polarity of PDI input DE. */
93#define DCU_THRESHOLD 0x028 /* Threshold */
94#define LS_BF_VS_SHIFT 16
95#define OUT_BUF_HIGH_SHIFT 8
96#define OUT_BUF_LOW_SHIFT 0
97#define DCU_INT_STATUS 0x02C /* Interrupt Status */
98#define DCU_INT_MASK 0x030 /* Interrupt Mask */
99#define DCU_COLBAR_1 0x034 /* COLBAR_1 */
100#define DCU_COLBAR_2 0x038 /* COLBAR_2 */

--- 54 unchanged lines hidden (view full) ---

155#define BPP24 0x5
156#define EN_LAYER (1 << 31) /* Enable the layer */
157#define DCU_CTRLDESCLn_5(n) DCU_CTRLDESCL(n, 5)
158#define DCU_CTRLDESCLn_6(n) DCU_CTRLDESCL(n, 6)
159#define DCU_CTRLDESCLn_7(n) DCU_CTRLDESCL(n, 7)
160#define DCU_CTRLDESCLn_8(n) DCU_CTRLDESCL(n, 8)
161#define DCU_CTRLDESCLn_9(n) DCU_CTRLDESCL(n, 9)
162
102#define DCU_THRESHOLD 0x028 /* Threshold */
103#define LS_BF_VS_SHIFT 16
104#define OUT_BUF_HIGH_SHIFT 8
105#define OUT_BUF_LOW_SHIFT 0
106#define DCU_INT_STATUS 0x02C /* Interrupt Status */
107#define DCU_INT_MASK 0x030 /* Interrupt Mask */
108#define DCU_COLBAR_1 0x034 /* COLBAR_1 */
109#define DCU_COLBAR_2 0x038 /* COLBAR_2 */

--- 54 unchanged lines hidden (view full) ---

164#define BPP24 0x5
165#define EN_LAYER (1 << 31) /* Enable the layer */
166#define DCU_CTRLDESCLn_5(n) DCU_CTRLDESCL(n, 5)
167#define DCU_CTRLDESCLn_6(n) DCU_CTRLDESCL(n, 6)
168#define DCU_CTRLDESCLn_7(n) DCU_CTRLDESCL(n, 7)
169#define DCU_CTRLDESCLn_8(n) DCU_CTRLDESCL(n, 8)
170#define DCU_CTRLDESCLn_9(n) DCU_CTRLDESCL(n, 9)
171
163#define DISPLAY_WIDTH 480
164#define DISPLAY_HEIGHT 272
172#define NUM_LAYERS 64
165
173
174struct panel_info {
175 uint32_t width;
176 uint32_t height;
177 uint32_t h_back_porch;
178 uint32_t h_pulse_width;
179 uint32_t h_front_porch;
180 uint32_t v_back_porch;
181 uint32_t v_pulse_width;
182 uint32_t v_front_porch;
183 uint32_t clk_div;
184 uint32_t backlight_pin;
185};
186
166struct dcu_softc {
167 struct resource *res[2];
168 bus_space_tag_t bst;
169 bus_space_handle_t bsh;
170 void *ih;
171 device_t dev;
172 device_t sc_fbd; /* fbd child */
173 struct fb_info sc_info;
187struct dcu_softc {
188 struct resource *res[2];
189 bus_space_tag_t bst;
190 bus_space_handle_t bsh;
191 void *ih;
192 device_t dev;
193 device_t sc_fbd; /* fbd child */
194 struct fb_info sc_info;
195 struct panel_info *panel;
174};
175
176static struct resource_spec dcu_spec[] = {
177 { SYS_RES_MEMORY, 0, RF_ACTIVE },
178 { SYS_RES_IRQ, 0, RF_ACTIVE },
179 { -1, 0 }
180};
181

--- 22 unchanged lines hidden (view full) ---

204 /* Ack interrupts */
205 reg = READ4(sc, DCU_INT_STATUS);
206 WRITE4(sc, DCU_INT_STATUS, reg);
207
208 /* TODO interrupt handler */
209}
210
211static int
196};
197
198static struct resource_spec dcu_spec[] = {
199 { SYS_RES_MEMORY, 0, RF_ACTIVE },
200 { SYS_RES_IRQ, 0, RF_ACTIVE },
201 { -1, 0 }
202};
203

--- 22 unchanged lines hidden (view full) ---

226 /* Ack interrupts */
227 reg = READ4(sc, DCU_INT_STATUS);
228 WRITE4(sc, DCU_INT_STATUS, reg);
229
230 /* TODO interrupt handler */
231}
232
233static int
234get_panel_info(struct dcu_softc *sc, struct panel_info *panel)
235{
236 phandle_t node;
237 pcell_t dts_value[3];
238 int len;
239
240 if ((node = ofw_bus_get_node(sc->dev)) == -1)
241 return (ENXIO);
242
243 /* panel size */
244 if ((len = OF_getproplen(node, "panel-size")) <= 0)
245 return (ENXIO);
246 OF_getprop(node, "panel-size", &dts_value, len);
247 panel->width = fdt32_to_cpu(dts_value[0]);
248 panel->height = fdt32_to_cpu(dts_value[1]);
249
250 /* hsync */
251 if ((len = OF_getproplen(node, "panel-hsync")) <= 0)
252 return (ENXIO);
253 OF_getprop(node, "panel-hsync", &dts_value, len);
254 panel->h_back_porch = fdt32_to_cpu(dts_value[0]);
255 panel->h_pulse_width = fdt32_to_cpu(dts_value[1]);
256 panel->h_front_porch = fdt32_to_cpu(dts_value[2]);
257
258 /* vsync */
259 if ((len = OF_getproplen(node, "panel-vsync")) <= 0)
260 return (ENXIO);
261 OF_getprop(node, "panel-vsync", &dts_value, len);
262 panel->v_back_porch = fdt32_to_cpu(dts_value[0]);
263 panel->v_pulse_width = fdt32_to_cpu(dts_value[1]);
264 panel->v_front_porch = fdt32_to_cpu(dts_value[2]);
265
266 /* clk divider */
267 if ((len = OF_getproplen(node, "panel-clk-div")) <= 0)
268 return (ENXIO);
269 OF_getprop(node, "panel-clk-div", &dts_value, len);
270 panel->clk_div = fdt32_to_cpu(dts_value[0]);
271
272 /* backlight pin */
273 if ((len = OF_getproplen(node, "panel-backlight-pin")) <= 0)
274 return (ENXIO);
275 OF_getprop(node, "panel-backlight-pin", &dts_value, len);
276 panel->backlight_pin = fdt32_to_cpu(dts_value[0]);
277
278 return (0);
279}
280
281static int
212dcu_init(struct dcu_softc *sc)
213{
282dcu_init(struct dcu_softc *sc)
283{
284 struct panel_info *panel;
214 int reg;
285 int reg;
286 int i;
215
287
288 panel = sc->panel;
289
216 /* Configure DCU */
217 reg = ((sc->sc_info.fb_height) << DELTA_Y_S);
218 reg |= (sc->sc_info.fb_width / 16);
219 WRITE4(sc, DCU_DISP_SIZE, reg);
220
290 /* Configure DCU */
291 reg = ((sc->sc_info.fb_height) << DELTA_Y_S);
292 reg |= (sc->sc_info.fb_width / 16);
293 WRITE4(sc, DCU_DISP_SIZE, reg);
294
221 /* TODO: export panel info to FDT */
222
223 reg = (2 << BP_H_SHIFT);
224 reg |= (41 << PW_H_SHIFT);
225 reg |= (2 << FP_H_SHIFT);
295 reg = (panel->h_back_porch << BP_H_SHIFT);
296 reg |= (panel->h_pulse_width << PW_H_SHIFT);
297 reg |= (panel->h_front_porch << FP_H_SHIFT);
226 WRITE4(sc, DCU_HSYN_PARA, reg);
227
298 WRITE4(sc, DCU_HSYN_PARA, reg);
299
228 reg = (2 << BP_V_SHIFT);
229 reg |= (10 << PW_V_SHIFT);
230 reg |= (2 << FP_V_SHIFT);
300 reg = (panel->v_back_porch << BP_V_SHIFT);
301 reg |= (panel->v_pulse_width << PW_V_SHIFT);
302 reg |= (panel->v_front_porch << FP_V_SHIFT);
231 WRITE4(sc, DCU_VSYN_PARA, reg);
232
233 WRITE4(sc, DCU_BGND, 0);
303 WRITE4(sc, DCU_VSYN_PARA, reg);
304
305 WRITE4(sc, DCU_BGND, 0);
234 WRITE4(sc, DCU_DIV_RATIO, 30);
306 WRITE4(sc, DCU_DIV_RATIO, panel->clk_div);
235
236 reg = (INV_VS | INV_HS);
237 WRITE4(sc, DCU_SYNPOL, reg);
238
307
308 reg = (INV_VS | INV_HS);
309 WRITE4(sc, DCU_SYNPOL, reg);
310
311 /* TODO: export to panel info */
239 reg = (0x3 << LS_BF_VS_SHIFT);
240 reg |= (0x78 << OUT_BUF_HIGH_SHIFT);
241 reg |= (0 << OUT_BUF_LOW_SHIFT);
242 WRITE4(sc, DCU_THRESHOLD, reg);
243
244 /* Mask all the interrupts */
245 WRITE4(sc, DCU_INT_MASK, 0xffffffff);
246
312 reg = (0x3 << LS_BF_VS_SHIFT);
313 reg |= (0x78 << OUT_BUF_HIGH_SHIFT);
314 reg |= (0 << OUT_BUF_LOW_SHIFT);
315 WRITE4(sc, DCU_THRESHOLD, reg);
316
317 /* Mask all the interrupts */
318 WRITE4(sc, DCU_INT_MASK, 0xffffffff);
319
320 /* Reset all layers */
321 for (i = 0; i < NUM_LAYERS; i++) {
322 WRITE4(sc, DCU_CTRLDESCLn_1(i), 0x0);
323 WRITE4(sc, DCU_CTRLDESCLn_2(i), 0x0);
324 WRITE4(sc, DCU_CTRLDESCLn_3(i), 0x0);
325 WRITE4(sc, DCU_CTRLDESCLn_4(i), 0x0);
326 WRITE4(sc, DCU_CTRLDESCLn_5(i), 0x0);
327 WRITE4(sc, DCU_CTRLDESCLn_6(i), 0x0);
328 WRITE4(sc, DCU_CTRLDESCLn_7(i), 0x0);
329 WRITE4(sc, DCU_CTRLDESCLn_8(i), 0x0);
330 WRITE4(sc, DCU_CTRLDESCLn_9(i), 0x0);
331 }
332
247 /* Setup first layer */
248 reg = (sc->sc_info.fb_width | (sc->sc_info.fb_height << 16));
249 WRITE4(sc, DCU_CTRLDESCLn_1(0), reg);
250 WRITE4(sc, DCU_CTRLDESCLn_2(0), 0x0);
251 WRITE4(sc, DCU_CTRLDESCLn_3(0), sc->sc_info.fb_pbase);
252 reg = (BPP24 << BPP_SHIFT);
253 reg |= EN_LAYER;
254 reg |= (0xFF << TRANS_SHIFT); /* completely opaque */

--- 13 unchanged lines hidden (view full) ---

268 WRITE4(sc, DCU_UPDATE_MODE, READREG);
269
270 return (0);
271}
272
273static int
274dcu_attach(device_t dev)
275{
333 /* Setup first layer */
334 reg = (sc->sc_info.fb_width | (sc->sc_info.fb_height << 16));
335 WRITE4(sc, DCU_CTRLDESCLn_1(0), reg);
336 WRITE4(sc, DCU_CTRLDESCLn_2(0), 0x0);
337 WRITE4(sc, DCU_CTRLDESCLn_3(0), sc->sc_info.fb_pbase);
338 reg = (BPP24 << BPP_SHIFT);
339 reg |= EN_LAYER;
340 reg |= (0xFF << TRANS_SHIFT); /* completely opaque */

--- 13 unchanged lines hidden (view full) ---

354 WRITE4(sc, DCU_UPDATE_MODE, READREG);
355
356 return (0);
357}
358
359static int
360dcu_attach(device_t dev)
361{
362 struct panel_info panel;
276 struct dcu_softc *sc;
363 struct dcu_softc *sc;
364 device_t gpio_dev;
277 int err;
278
279 sc = device_get_softc(dev);
365 int err;
366
367 sc = device_get_softc(dev);
368 sc->dev = dev;
280
281 if (bus_alloc_resources(dev, dcu_spec, sc->res)) {
282 device_printf(dev, "could not allocate resources\n");
283 return (ENXIO);
284 }
285
286 /* Memory interface */
287 sc->bst = rman_get_bustag(sc->res[0]);
288 sc->bsh = rman_get_bushandle(sc->res[0]);
289
290 /* Setup interrupt handler */
291 err = bus_setup_intr(dev, sc->res[1], INTR_TYPE_BIO | INTR_MPSAFE,
292 NULL, dcu_intr, sc, &sc->ih);
293 if (err) {
294 device_printf(dev, "Unable to alloc interrupt resource.\n");
295 return (ENXIO);
296 }
297
369
370 if (bus_alloc_resources(dev, dcu_spec, sc->res)) {
371 device_printf(dev, "could not allocate resources\n");
372 return (ENXIO);
373 }
374
375 /* Memory interface */
376 sc->bst = rman_get_bustag(sc->res[0]);
377 sc->bsh = rman_get_bushandle(sc->res[0]);
378
379 /* Setup interrupt handler */
380 err = bus_setup_intr(dev, sc->res[1], INTR_TYPE_BIO | INTR_MPSAFE,
381 NULL, dcu_intr, sc, &sc->ih);
382 if (err) {
383 device_printf(dev, "Unable to alloc interrupt resource.\n");
384 return (ENXIO);
385 }
386
387 if (get_panel_info(sc, &panel)) {
388 device_printf(dev, "Can't get panel info\n");
389 return (ENXIO);
390 }
391
392 sc->panel = &panel;
393
298 /* Bypass timing control (used for raw lcd panels) */
299 tcon_bypass();
300
394 /* Bypass timing control (used for raw lcd panels) */
395 tcon_bypass();
396
301 sc->sc_info.fb_width = DISPLAY_WIDTH;
302 sc->sc_info.fb_height = DISPLAY_HEIGHT;
397 /* Get the GPIO device, we need this to give power to USB */
398 gpio_dev = devclass_get_device(devclass_find("gpio"), 0);
399 if (gpio_dev == NULL) {
400 device_printf(sc->dev, "Error: failed to get the GPIO dev\n");
401 return (1);
402 }
403
404 /* Turn on backlight */
405 /* TODO: Use FlexTimer/PWM */
406 GPIO_PIN_SETFLAGS(gpio_dev, panel.backlight_pin, GPIO_PIN_OUTPUT);
407 GPIO_PIN_SET(gpio_dev, panel.backlight_pin, GPIO_PIN_HIGH);
408
409 sc->sc_info.fb_width = panel.width;
410 sc->sc_info.fb_height = panel.height;
303 sc->sc_info.fb_stride = sc->sc_info.fb_width * 3;
304 sc->sc_info.fb_bpp = sc->sc_info.fb_depth = 24;
305 sc->sc_info.fb_size = sc->sc_info.fb_height * sc->sc_info.fb_stride;
306 sc->sc_info.fb_vbase = (intptr_t)contigmalloc(sc->sc_info.fb_size,
307 M_DEVBUF, M_ZERO, 0, ~0, PAGE_SIZE, 0);
308 sc->sc_info.fb_pbase = (intptr_t)vtophys(sc->sc_info.fb_vbase);
309
310#if 0

--- 49 unchanged lines hidden ---
411 sc->sc_info.fb_stride = sc->sc_info.fb_width * 3;
412 sc->sc_info.fb_bpp = sc->sc_info.fb_depth = 24;
413 sc->sc_info.fb_size = sc->sc_info.fb_height * sc->sc_info.fb_stride;
414 sc->sc_info.fb_vbase = (intptr_t)contigmalloc(sc->sc_info.fb_size,
415 M_DEVBUF, M_ZERO, 0, ~0, PAGE_SIZE, 0);
416 sc->sc_info.fb_pbase = (intptr_t)vtophys(sc->sc_info.fb_vbase);
417
418#if 0

--- 49 unchanged lines hidden ---