-
Notifications
You must be signed in to change notification settings - Fork 27
Development
I'm working on an abstraction that I hope to get merged in some form: tinydrm-panel.h, tinydrm-panel.c
Build documentation:
# install sphinx
$ make htmldocs
Result is in Documentation/output.
- https://dri.freedesktop.org/docs/drm/gpu/tinydrm.html
- https://dri.freedesktop.org/docs/drm/process/index.html
I did a test some months back using a hacked modetest rendering a dumb buffer on vc4 and scanned out with tinydrm. This worked.
I recently tried the same using X windows, but failed: https://github.com/anholt/linux/issues/10
- https://01.org/linuxgraphics/gfx-docs/drm/gpu/drm-mm.html#prime-buffer-sharing
- https://dri.freedesktop.org/docs/drm/driver-api/dma-buf.html
modetest is a simple tool to test drm drivers.
Build
$ sudo apt-get -y install autoconf libtool xutils-dev libpthread-stubs0-dev
$ git clone https://github.com/freedreno/libdrm
$ cd libdrm
$ ./autogen.sh
$ make
Find connector id
$ ./tests/modetest/modetest -M "mi0283qt" -c
Connectors:
id encoder status name size (mm) modes encoders
25 28 connected Virtual-1 58x43 1 28
modes:
name refresh (Hz) hdisp hss hse htot vdisp vss vse vtot)
320x240 0 320 320 320 320 240 240 240 240 1 flags: ; type: preferred, driver
props:
2 DPMS:
flags: enum
enums: On=0 Standby=1 Suspend=2 Off=3
value: 0
Display a test image
$ ./tests/modetest/modetest -M "mi0283qt" -s 25:320x240@RG16
setting mode 320x240-0Hz@RG16 on connectors 25, crtc 27
<press enter to stop>
(RG16 is RGB565, XR24 is XRGB8888)
How fast is it
$ ./tests/modetest/modetest -M "mi0283qt" -s 25:320x240@RG16 -v
setting mode 320x240-0Hz@RG16 on connectors 25, crtc 27
freq: 31.44Hz
freq: 31.44Hz
freq: 31.44Hz
freq: 31.44Hz
freq: 31.44Hz
<press enter to stop>
drm_debug
Turn on most drm debug messages
$ echo 0xf | sudo tee /sys/module/drm/parameters/debug
From include/drm/drmP.h
#define DRM_UT_CORE 0x01
#define DRM_UT_DRIVER 0x02
#define DRM_UT_KMS 0x04
#define DRM_UT_PRIME 0x08
#define DRM_UT_ATOMIC 0x10
#define DRM_UT_VBL 0x20
#define DRM_UT_STATE 0x40
mipi_dbi
Turn on and off display:
$ echo "28" | sudo tee /sys/kernel/debug/dri/0/command
$ echo "29" | sudo tee /sys/kernel/debug/dri/0/command
Dump MIPI DCS commands:
$ sudo cat /sys/kernel/debug/dri/0/command
04: 000000
06: 00
07: 00
08: 00
09: 94530400
0a: 9c
0b: 28
0c: 05
0d: 00
0e: 00
0f: c0
2e: 00c4
3e: 00c4
45: 00
52: 00
54: 00
56: 00
5f: 00
a1: 00
a8: 00
Use tool from tinydrm repo:
$ sudo ./tinydrm/tools/mipi-dcs
File: /sys/kernel/debug/dri/0/command
GET_DISPLAY_ID(04h): 000000 (0b0)
ID1 = 00
ID2 = 00
ID3 = 00
GET_RED_CHANNEL(06h): 00 (0b0)
GET_GREEN_CHANNEL(07h): 00 (0b0)
GET_BLUE_CHANNEL(08h): 00 (0b0)
GET_DISPLAY_STATUS(09h): 94530400 (0b10010100010100110000010000000000)
D31=1: Booster voltage status: On
D30=0: Row address order
D29=0: Column address order
D28=1: Row/column exchange
D27=0: Vertical refresh: Top to Bottom
D26=1: RGB/BGR order: BGR
D25=0: Horizontal refresh order: Left to Right
D24=0: Reserved
D23=0: Reserved
D[22:20]=2373: Interface color pixel format: 1 0 1
D19=0: Idle mode: Off
D18=0: Partial mode: Off
D17=1: Sleep: Out
D16=1: Display normal mode: On
D15=0: Vertical scrolling status: Off
D14=0: Reserved
D13=0: Inversion status
D12=0: All pixel ON
D11=0: All pixel OFF
D10=1: Display: On
D9=0: Tearing effect line: Off
D[8:6]=38882320: Gamma curve selection: 0 0 0
D5=0: Tearing effect line mode: Mode 1, V-Blanking only
D4=0: Reserved
D3=0: Reserved
D2=0: Reserved
D1=0: Reserved
D0=0: Reserved
GET_POWER_MODE(0Ah): 9c (0b10011100)
D7=1: Booster On
D6=0: Idle Mode Off
D5=0: Partial Mode Off
D4=1: Sleep Out Mode
D3=1: Display Normal Mode On
D2=1: Display is On
D1=0: Reserved
D0=0: Reserved
GET_ADDRESS_MODE(0Bh): 28 (0b101000)
D7=0: Page Address Order: Top to Bottom
D6=0: Column Address Order: Left to Right
D5=1: Page/Column Order: Reverse Mode
D4=0: Line Address Order: LCD Refresh Top to Bottom
D3=1: RGB/BGR Order: BGR
D2=0: Display Data Latch Data Order: LCD Refresh Left to Right
D1=0: Reserved
D0=0: Reserved
GET_PIXEL_FORMAT(0Ch): 05 (0b101)
D7=0: Reserved
D[6:4]=0: DPI: Reserved
D3=0: Reserved
D[2:0]=5: DBI: 16 bits/pixel
GET_DISPLAY_MODE(0Dh): 00 (0b0)
D7=0: Vertical Scrolling Status: Off
D6=0: Reserved
D5=0: Inversion: Off
D4=0: Reserved
D3=0: Reserved
D[2:0]=0: Gamma Curve Selection: GC0
GET_SIGNAL_MODE(0Eh): 00 (0b0)
D7=0: Tearing Effect Line: Off
D6=0: Tearing Effect Line Output Mode: Mode 1
D5=0: Reserved
D4=0: Reserved
D3=0: Reserved
D2=0: Reserved
D1=0: Reserved
D0=0: Reserved
GET_DIAGNOSTIC_RESULT(0Fh): c0 (0b11000000)
D7=1: Register Loading Detection: OK
D6=1: Functionality Detection: OK
D5=0: Chip Attachment Detection: OK or unimplemented
D4=0: Display Glass Break Detection: OK or unimplemented
D3=0: Reserved
D2=0: Reserved
D1=0: Reserved
D0=0: Reserved
READ_MEMORY_START(2Eh): 0000 (0b0)
READ_MEMORY_CONTINUE(3Eh): 0000 (0b0)
GET_SCANLINE(45h): 00 (0b0)
GET_DISPLAY_BRIGHTNESS(52h): 00 (0b0)
GET_CONTROL_DISPLAY(54h): 00 (0b0)
GET_POWER_SAVE(56h): 00 (0b0)
GET_CABC_MIN_BRIGHTNESS(5Fh): 00 (0b0)
READ_DDB_START(A1h): 00 (0b0)
READ_DDB_CONTINUE(A8h): 00 (0b0)
regmap
Regmap isn't currently used in tinydrm, but might be used as a way to represent a LCD register.
Event tracing can be used see what's been written to the registers:
#enable
echo 1 | sudo tee /sys/kernel/debug/tracing/events/regmap/regmap_reg_write/enable
echo 1 | sudo tee /sys/kernel/debug/tracing/events/regmap/regmap_reg_read/enable
#disable
echo | sudo tee /sys/kernel/debug/tracing/set_event
#start
echo 1 | sudo tee /sys/kernel/debug/tracing/tracing_on
#stop
echo 0 | sudo tee /sys/kernel/debug/tracing/tracing_on
#view
sudo cat /sys/kernel/debug/tracing/trace
#clear
echo | sudo tee /sys/kernel/debug/tracing/trace
tinydrm doesn't support platform data, but it's still possible use it without Device Tree. This example is taken from my work on fb_ili9325.
#include <linux/gpio/machine.h>
#include <linux/property.h>
#include <linux/spi/spi.h>
static const struct spi_board_info hy28a = {
.modalias = "fb_ili9320",
.max_speed_hz = 32000000,
.bus_num = 0,
.chip_select = 0,
.mode = SPI_MODE_3,
};
static struct property_entry hy28a_properties[] = {
PROPERTY_ENTRY_BOOL("bgr"),
PROPERTY_ENTRY_U32("rotation", 270),
{ },
};
static struct gpiod_lookup_table hy28a_gpios = {
.dev_id = "spi0.0",
.table = {
GPIO_LOOKUP("pinctrl-bcm2835", 25, "reset", GPIO_ACTIVE_HIGH),
GPIO_LOOKUP("pinctrl-bcm2835", 18, "led", GPIO_ACTIVE_LOW),
{ },
},
};
static int bus_notifier_call(struct notifier_block *n, unsigned long action, void *data)
{
struct device *dev = data;
if (action == BUS_NOTIFY_ADD_DEVICE) {
if (!strcmp(dev_name(dev), "spi0.0")) {
dev_info(dev, "hy28a registered\n");
device_add_properties(dev, hy28a_properties);
}
}
return NOTIFY_DONE;
}
static struct notifier_block bus_notifier = {
.notifier_call = bus_notifier_call,
};
static int __init hy28a_register(void)
{
int ret;
gpiod_add_lookup_table(&hy28a_gpios);
bus_register_notifier(&spi_bus_type, &bus_notifier);
ret = spi_register_board_info(&hy28a, 1);
if (ret) {
pr_err("Failed to register hy28a\n");
return ret;
}
return 0;
}
gpiod_add_lookup_table() isn't exported so this can't be done from a loadable module.