Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
linux
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
2
Pull requests
0
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
72427ea
Documentation
arch
block
crypto
drivers
accessibility
acpi
amba
ata
atm
auxdisplay
base
bcma
block
bluetooth
bus
cdrom
char
clk
clocksource
connector
cpufreq
cpuidle
crypto
dca
devfreq
dio
dma-buf
dma
edac
eisa
extcon
firewire
firmware
fmc
gpio
gpu
drm
armada
ast
bochs
bridge
cirrus
exynos
gma500
i2c
i810
i915
mga
mgag200
msm
nouveau
omapdrm
panel
Kconfig
Makefile
panel-ld9040.c
panel-s6e8aa0.c
panel-simple.c
qxl
r128
radeon
rcar-du
savage
shmobile
sis
sti
tdfx
tegra
tilcdc
ttm
udl
via
vmwgfx
Kconfig
Makefile
README.drm
ati_pcigart.c
drm_agpsupport.c
drm_auth.c
drm_bufs.c
drm_cache.c
drm_context.c
drm_crtc.c
drm_crtc_helper.c
drm_crtc_internal.h
drm_debugfs.c
drm_dma.c
drm_dp_helper.c
drm_dp_mst_topology.c
drm_drv.c
drm_edid.c
drm_edid_load.c
drm_encoder_slave.c
drm_fb_cma_helper.c
drm_fb_helper.c
drm_flip_work.c
drm_fops.c
drm_gem.c
drm_gem_cma_helper.c
drm_global.c
drm_hashtab.c
drm_info.c
drm_internal.h
drm_ioc32.c
drm_ioctl.c
drm_irq.c
drm_legacy.h
drm_lock.c
drm_memory.c
drm_mipi_dsi.c
drm_mm.c
drm_modes.c
drm_modeset_lock.c
drm_of.c
drm_panel.c
drm_pci.c
drm_plane_helper.c
drm_platform.c
drm_prime.c
drm_probe_helper.c
drm_rect.c
drm_scatter.c
drm_sysfs.c
drm_trace.h
drm_trace_points.c
drm_vm.c
drm_vma_manager.c
host1x
ipu-v3
vga
Makefile
hid
hsi
hv
hwmon
hwspinlock
i2c
ide
idle
iio
infiniband
input
iommu
ipack
irqchip
isdn
leds
lguest
macintosh
mailbox
mcb
md
media
memory
memstick
message
mfd
misc
mmc
mtd
net
nfc
ntb
nubus
of
oprofile
parisc
parport
pci
pcmcia
phy
pinctrl
platform
pnp
power
powercap
pps
ps3
ptp
pwm
rapidio
ras
regulator
remoteproc
reset
rpmsg
rtc
s390
sbus
scsi
sfi
sh
sn
soc
spi
spmi
ssb
staging
target
tc
thermal
thunderbolt
tty
uio
usb
uwb
vfio
vhost
video
virt
virtio
vlynq
vme
w1
watchdog
xen
zorro
Kconfig
Makefile
firmware
fs
include
init
ipc
kernel
lib
mm
net
samples
scripts
security
sound
tools
usr
virt
.gitignore
.mailmap
COPYING
CREDITS
Kbuild
Kconfig
MAINTAINERS
Makefile
README
REPORTING-BUGS
Breadcrumbs
linux
/
drivers
/
gpu
/
drm
/
panel
/
panel-simple.c
Copy path
Blame
Blame
Latest commit
History
History
906 lines (772 loc) · 19.9 KB
Breadcrumbs
linux
/
drivers
/
gpu
/
drm
/
panel
/
panel-simple.c
Top
File metadata and controls
Code
Blame
906 lines (772 loc) · 19.9 KB
Raw
/* * Copyright (C) 2013, NVIDIA Corporation. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sub license, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include <linux/backlight.h> #include <linux/gpio/consumer.h> #include <linux/module.h> #include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> #include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_mipi_dsi.h> #include <drm/drm_panel.h> struct panel_desc { const struct drm_display_mode *modes; unsigned int num_modes; unsigned int bpc; struct { unsigned int width; unsigned int height; } size; /** * @prepare: the time (in milliseconds) that it takes for the panel to * become ready and start receiving video data * @enable: the time (in milliseconds) that it takes for the panel to * display the first valid frame after starting to receive * video data * @disable: the time (in milliseconds) that it takes for the panel to * turn the display off (no content is visible) * @unprepare: the time (in milliseconds) that it takes for the panel * to power itself down completely */ struct { unsigned int prepare; unsigned int enable; unsigned int disable; unsigned int unprepare; } delay; }; struct panel_simple { struct drm_panel base; bool prepared; bool enabled; const struct panel_desc *desc; struct backlight_device *backlight; struct regulator *supply; struct i2c_adapter *ddc; struct gpio_desc *enable_gpio; }; static inline struct panel_simple *to_panel_simple(struct drm_panel *panel) { return container_of(panel, struct panel_simple, base); } static int panel_simple_get_fixed_modes(struct panel_simple *panel) { struct drm_connector *connector = panel->base.connector; struct drm_device *drm = panel->base.drm; struct drm_display_mode *mode; unsigned int i, num = 0; if (!panel->desc) return 0; for (i = 0; i < panel->desc->num_modes; i++) { const struct drm_display_mode *m = &panel->desc->modes[i]; mode = drm_mode_duplicate(drm, m); if (!mode) { dev_err(drm->dev, "failed to add mode %ux%u@%u\n", m->hdisplay, m->vdisplay, m->vrefresh); continue; } drm_mode_set_name(mode); drm_mode_probed_add(connector, mode); num++; } connector->display_info.bpc = panel->desc->bpc; connector->display_info.width_mm = panel->desc->size.width; connector->display_info.height_mm = panel->desc->size.height; return num; } static int panel_simple_disable(struct drm_panel *panel) { struct panel_simple *p = to_panel_simple(panel); if (!p->enabled) return 0; if (p->backlight) { p->backlight->props.power = FB_BLANK_POWERDOWN; backlight_update_status(p->backlight); } if (p->desc->delay.disable) msleep(p->desc->delay.disable); p->enabled = false; return 0; } static int panel_simple_unprepare(struct drm_panel *panel) { struct panel_simple *p = to_panel_simple(panel); if (!p->prepared) return 0; if (p->enable_gpio) gpiod_set_value_cansleep(p->enable_gpio, 0); regulator_disable(p->supply); if (p->desc->delay.unprepare) msleep(p->desc->delay.unprepare); p->prepared = false; return 0; } static int panel_simple_prepare(struct drm_panel *panel) { struct panel_simple *p = to_panel_simple(panel); int err; if (p->prepared) return 0; err = regulator_enable(p->supply); if (err < 0) { dev_err(panel->dev, "failed to enable supply: %d\n", err); return err; } if (p->enable_gpio) gpiod_set_value_cansleep(p->enable_gpio, 1); if (p->desc->delay.prepare) msleep(p->desc->delay.prepare); p->prepared = true; return 0; } static int panel_simple_enable(struct drm_panel *panel) { struct panel_simple *p = to_panel_simple(panel); if (p->enabled) return 0; if (p->desc->delay.enable) msleep(p->desc->delay.enable); if (p->backlight) { p->backlight->props.power = FB_BLANK_UNBLANK; backlight_update_status(p->backlight); } p->enabled = true; return 0; } static int panel_simple_get_modes(struct drm_panel *panel) { struct panel_simple *p = to_panel_simple(panel); int num = 0; /* probe EDID if a DDC bus is available */ if (p->ddc) { struct edid *edid = drm_get_edid(panel->connector, p->ddc); drm_mode_connector_update_edid_property(panel->connector, edid); if (edid) { num += drm_add_edid_modes(panel->connector, edid); kfree(edid); } } /* add hard-coded panel modes */ num += panel_simple_get_fixed_modes(p); return num; } static const struct drm_panel_funcs panel_simple_funcs = { .disable = panel_simple_disable, .unprepare = panel_simple_unprepare, .prepare = panel_simple_prepare, .enable = panel_simple_enable, .get_modes = panel_simple_get_modes, }; static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) { struct device_node *backlight, *ddc; struct panel_simple *panel; int err; panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL); if (!panel) return -ENOMEM; panel->enabled = false; panel->prepared = false; panel->desc = desc; panel->supply = devm_regulator_get(dev, "power"); if (IS_ERR(panel->supply)) return PTR_ERR(panel->supply); panel->enable_gpio = devm_gpiod_get_optional(dev, "enable"); if (IS_ERR(panel->enable_gpio)) { err = PTR_ERR(panel->enable_gpio); dev_err(dev, "failed to request GPIO: %d\n", err); return err; } if (panel->enable_gpio) { err = gpiod_direction_output(panel->enable_gpio, 0); if (err < 0) { dev_err(dev, "failed to setup GPIO: %d\n", err); return err; } } backlight = of_parse_phandle(dev->of_node, "backlight", 0); if (backlight) { panel->backlight = of_find_backlight_by_node(backlight); of_node_put(backlight); if (!panel->backlight) return -EPROBE_DEFER; } ddc = of_parse_phandle(dev->of_node, "ddc-i2c-bus", 0); if (ddc) { panel->ddc = of_find_i2c_adapter_by_node(ddc); of_node_put(ddc); if (!panel->ddc) { err = -EPROBE_DEFER; goto free_backlight; } } drm_panel_init(&panel->base); panel->base.dev = dev; panel->base.funcs = &panel_simple_funcs; err = drm_panel_add(&panel->base); if (err < 0) goto free_ddc; dev_set_drvdata(dev, panel); return 0; free_ddc: if (panel->ddc) put_device(&panel->ddc->dev); free_backlight: if (panel->backlight) put_device(&panel->backlight->dev); return err; } static int panel_simple_remove(struct device *dev) { struct panel_simple *panel = dev_get_drvdata(dev); drm_panel_detach(&panel->base); drm_panel_remove(&panel->base); panel_simple_disable(&panel->base); panel_simple_unprepare(&panel->base); if (panel->ddc) put_device(&panel->ddc->dev); if (panel->backlight) put_device(&panel->backlight->dev); return 0; } static void panel_simple_shutdown(struct device *dev) { struct panel_simple *panel = dev_get_drvdata(dev); panel_simple_disable(&panel->base); panel_simple_unprepare(&panel->base); } static const struct drm_display_mode auo_b101aw03_mode = { .clock = 51450, .hdisplay = 1024, .hsync_start = 1024 + 156, .hsync_end = 1024 + 156 + 8, .htotal = 1024 + 156 + 8 + 156, .vdisplay = 600, .vsync_start = 600 + 16, .vsync_end = 600 + 16 + 6, .vtotal = 600 + 16 + 6 + 16, .vrefresh = 60, }; static const struct panel_desc auo_b101aw03 = { .modes = &auo_b101aw03_mode, .num_modes = 1, .bpc = 6, .size = { .width = 223, .height = 125, }, }; static const struct drm_display_mode auo_b101xtn01_mode = { .clock = 72000, .hdisplay = 1366, .hsync_start = 1366 + 20, .hsync_end = 1366 + 20 + 70, .htotal = 1366 + 20 + 70, .vdisplay = 768, .vsync_start = 768 + 14, .vsync_end = 768 + 14 + 42, .vtotal = 768 + 14 + 42, .vrefresh = 60, .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, }; static const struct panel_desc auo_b101xtn01 = { .modes = &auo_b101xtn01_mode, .num_modes = 1, .bpc = 6, .size = { .width = 223, .height = 125, }, }; static const struct drm_display_mode auo_b133xtn01_mode = { .clock = 69500, .hdisplay = 1366, .hsync_start = 1366 + 48, .hsync_end = 1366 + 48 + 32, .htotal = 1366 + 48 + 32 + 20, .vdisplay = 768, .vsync_start = 768 + 3, .vsync_end = 768 + 3 + 6, .vtotal = 768 + 3 + 6 + 13, .vrefresh = 60, }; static const struct panel_desc auo_b133xtn01 = { .modes = &auo_b133xtn01_mode, .num_modes = 1, .bpc = 6, .size = { .width = 293, .height = 165, }, }; static const struct drm_display_mode auo_b133htn01_mode = { .clock = 150660, .hdisplay = 1920, .hsync_start = 1920 + 172, .hsync_end = 1920 + 172 + 80, .htotal = 1920 + 172 + 80 + 60, .vdisplay = 1080, .vsync_start = 1080 + 25, .vsync_end = 1080 + 25 + 10, .vtotal = 1080 + 25 + 10 + 10, .vrefresh = 60, }; static const struct panel_desc auo_b133htn01 = { .modes = &auo_b133htn01_mode, .num_modes = 1, .size = { .width = 293, .height = 165, }, .delay = { .prepare = 105, .enable = 20, .unprepare = 50, }, }; static const struct drm_display_mode chunghwa_claa101wa01a_mode = { .clock = 72070, .hdisplay = 1366, .hsync_start = 1366 + 58, .hsync_end = 1366 + 58 + 58, .htotal = 1366 + 58 + 58 + 58, .vdisplay = 768, .vsync_start = 768 + 4, .vsync_end = 768 + 4 + 4, .vtotal = 768 + 4 + 4 + 4, .vrefresh = 60, }; static const struct panel_desc chunghwa_claa101wa01a = { .modes = &chunghwa_claa101wa01a_mode, .num_modes = 1, .bpc = 6, .size = { .width = 220, .height = 120, }, }; static const struct drm_display_mode chunghwa_claa101wb01_mode = { .clock = 69300, .hdisplay = 1366, .hsync_start = 1366 + 48, .hsync_end = 1366 + 48 + 32, .htotal = 1366 + 48 + 32 + 20, .vdisplay = 768, .vsync_start = 768 + 16, .vsync_end = 768 + 16 + 8, .vtotal = 768 + 16 + 8 + 16, .vrefresh = 60, }; static const struct panel_desc chunghwa_claa101wb01 = { .modes = &chunghwa_claa101wb01_mode, .num_modes = 1, .bpc = 6, .size = { .width = 223, .height = 125, }, }; static const struct drm_display_mode edt_et057090dhu_mode = { .clock = 25175, .hdisplay = 640, .hsync_start = 640 + 16, .hsync_end = 640 + 16 + 30, .htotal = 640 + 16 + 30 + 114, .vdisplay = 480, .vsync_start = 480 + 10, .vsync_end = 480 + 10 + 3, .vtotal = 480 + 10 + 3 + 32, .vrefresh = 60, .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, }; static const struct panel_desc edt_et057090dhu = { .modes = &edt_et057090dhu_mode, .num_modes = 1, .bpc = 6, .size = { .width = 115, .height = 86, }, }; static const struct drm_display_mode edt_etm0700g0dh6_mode = { .clock = 33260, .hdisplay = 800, .hsync_start = 800 + 40, .hsync_end = 800 + 40 + 128, .htotal = 800 + 40 + 128 + 88, .vdisplay = 480, .vsync_start = 480 + 10, .vsync_end = 480 + 10 + 2, .vtotal = 480 + 10 + 2 + 33, .vrefresh = 60, .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, }; static const struct panel_desc edt_etm0700g0dh6 = { .modes = &edt_etm0700g0dh6_mode, .num_modes = 1, .bpc = 6, .size = { .width = 152, .height = 91, }, }; static const struct drm_display_mode foxlink_fl500wvr00_a0t_mode = { .clock = 32260, .hdisplay = 800, .hsync_start = 800 + 168, .hsync_end = 800 + 168 + 64, .htotal = 800 + 168 + 64 + 88, .vdisplay = 480, .vsync_start = 480 + 37, .vsync_end = 480 + 37 + 2, .vtotal = 480 + 37 + 2 + 8, .vrefresh = 60, }; static const struct panel_desc foxlink_fl500wvr00_a0t = { .modes = &foxlink_fl500wvr00_a0t_mode, .num_modes = 1, .size = { .width = 108, .height = 65, }, }; static const struct drm_display_mode innolux_n116bge_mode = { .clock = 71000, .hdisplay = 1366, .hsync_start = 1366 + 64, .hsync_end = 1366 + 64 + 6, .htotal = 1366 + 64 + 6 + 64, .vdisplay = 768, .vsync_start = 768 + 8, .vsync_end = 768 + 8 + 4, .vtotal = 768 + 8 + 4 + 8, .vrefresh = 60, .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, }; static const struct panel_desc innolux_n116bge = { .modes = &innolux_n116bge_mode, .num_modes = 1, .bpc = 6, .size = { .width = 256, .height = 144, }, }; static const struct drm_display_mode innolux_n156bge_l21_mode = { .clock = 69300, .hdisplay = 1366, .hsync_start = 1366 + 16, .hsync_end = 1366 + 16 + 34, .htotal = 1366 + 16 + 34 + 50, .vdisplay = 768, .vsync_start = 768 + 2, .vsync_end = 768 + 2 + 6, .vtotal = 768 + 2 + 6 + 12, .vrefresh = 60, }; static const struct panel_desc innolux_n156bge_l21 = { .modes = &innolux_n156bge_l21_mode, .num_modes = 1, .bpc = 6, .size = { .width = 344, .height = 193, }, }; static const struct drm_display_mode lg_lp129qe_mode = { .clock = 285250, .hdisplay = 2560, .hsync_start = 2560 + 48, .hsync_end = 2560 + 48 + 32, .htotal = 2560 + 48 + 32 + 80, .vdisplay = 1700, .vsync_start = 1700 + 3, .vsync_end = 1700 + 3 + 10, .vtotal = 1700 + 3 + 10 + 36, .vrefresh = 60, }; static const struct panel_desc lg_lp129qe = { .modes = &lg_lp129qe_mode, .num_modes = 1, .bpc = 8, .size = { .width = 272, .height = 181, }, }; static const struct drm_display_mode samsung_ltn101nt05_mode = { .clock = 54030, .hdisplay = 1024, .hsync_start = 1024 + 24, .hsync_end = 1024 + 24 + 136, .htotal = 1024 + 24 + 136 + 160, .vdisplay = 600, .vsync_start = 600 + 3, .vsync_end = 600 + 3 + 6, .vtotal = 600 + 3 + 6 + 61, .vrefresh = 60, }; static const struct panel_desc samsung_ltn101nt05 = { .modes = &samsung_ltn101nt05_mode, .num_modes = 1, .bpc = 6, .size = { .width = 1024, .height = 600, }, }; static const struct of_device_id platform_of_match[] = { { .compatible = "auo,b101aw03", .data = &auo_b101aw03, }, { .compatible = "auo,b101xtn01", .data = &auo_b101xtn01, }, { .compatible = "auo,b133htn01", .data = &auo_b133htn01, }, { .compatible = "auo,b133xtn01", .data = &auo_b133xtn01, }, { .compatible = "chunghwa,claa101wa01a", .data = &chunghwa_claa101wa01a }, { .compatible = "chunghwa,claa101wb01", .data = &chunghwa_claa101wb01 }, { .compatible = "edt,et057090dhu", .data = &edt_et057090dhu, }, { .compatible = "edt,et070080dh6", .data = &edt_etm0700g0dh6, }, { .compatible = "edt,etm0700g0dh6", .data = &edt_etm0700g0dh6, }, { .compatible = "foxlink,fl500wvr00-a0t", .data = &foxlink_fl500wvr00_a0t, }, { .compatible = "innolux,n116bge", .data = &innolux_n116bge, }, { .compatible = "innolux,n156bge-l21", .data = &innolux_n156bge_l21, }, { .compatible = "lg,lp129qe", .data = &lg_lp129qe, }, { .compatible = "samsung,ltn101nt05", .data = &samsung_ltn101nt05, }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, platform_of_match); static int panel_simple_platform_probe(struct platform_device *pdev) { const struct of_device_id *id; id = of_match_node(platform_of_match, pdev->dev.of_node); if (!id) return -ENODEV; return panel_simple_probe(&pdev->dev, id->data); } static int panel_simple_platform_remove(struct platform_device *pdev) { return panel_simple_remove(&pdev->dev); } static void panel_simple_platform_shutdown(struct platform_device *pdev) { panel_simple_shutdown(&pdev->dev); } static struct platform_driver panel_simple_platform_driver = { .driver = { .name = "panel-simple", .owner = THIS_MODULE, .of_match_table = platform_of_match, }, .probe = panel_simple_platform_probe, .remove = panel_simple_platform_remove, .shutdown = panel_simple_platform_shutdown, }; struct panel_desc_dsi { struct panel_desc desc; unsigned long flags; enum mipi_dsi_pixel_format format; unsigned int lanes; }; static const struct drm_display_mode lg_ld070wx3_sl01_mode = { .clock = 71000, .hdisplay = 800, .hsync_start = 800 + 32, .hsync_end = 800 + 32 + 1, .htotal = 800 + 32 + 1 + 57, .vdisplay = 1280, .vsync_start = 1280 + 28, .vsync_end = 1280 + 28 + 1, .vtotal = 1280 + 28 + 1 + 14, .vrefresh = 60, }; static const struct panel_desc_dsi lg_ld070wx3_sl01 = { .desc = { .modes = &lg_ld070wx3_sl01_mode, .num_modes = 1, .size = { .width = 94, .height = 151, }, }, .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_CLOCK_NON_CONTINUOUS, .format = MIPI_DSI_FMT_RGB888, .lanes = 4, }; static const struct drm_display_mode lg_lh500wx1_sd03_mode = { .clock = 67000, .hdisplay = 720, .hsync_start = 720 + 12, .hsync_end = 720 + 12 + 4, .htotal = 720 + 12 + 4 + 112, .vdisplay = 1280, .vsync_start = 1280 + 8, .vsync_end = 1280 + 8 + 4, .vtotal = 1280 + 8 + 4 + 12, .vrefresh = 60, }; static const struct panel_desc_dsi lg_lh500wx1_sd03 = { .desc = { .modes = &lg_lh500wx1_sd03_mode, .num_modes = 1, .size = { .width = 62, .height = 110, }, }, .flags = MIPI_DSI_MODE_VIDEO, .format = MIPI_DSI_FMT_RGB888, .lanes = 4, }; static const struct drm_display_mode panasonic_vvx10f004b00_mode = { .clock = 157200, .hdisplay = 1920, .hsync_start = 1920 + 154, .hsync_end = 1920 + 154 + 16, .htotal = 1920 + 154 + 16 + 32, .vdisplay = 1200, .vsync_start = 1200 + 17, .vsync_end = 1200 + 17 + 2, .vtotal = 1200 + 17 + 2 + 16, .vrefresh = 60, }; static const struct panel_desc_dsi panasonic_vvx10f004b00 = { .desc = { .modes = &panasonic_vvx10f004b00_mode, .num_modes = 1, .size = { .width = 217, .height = 136, }, }, .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_CLOCK_NON_CONTINUOUS, .format = MIPI_DSI_FMT_RGB888, .lanes = 4, }; static const struct of_device_id dsi_of_match[] = { { .compatible = "lg,ld070wx3-sl01", .data = &lg_ld070wx3_sl01 }, { .compatible = "lg,lh500wx1-sd03", .data = &lg_lh500wx1_sd03 }, { .compatible = "panasonic,vvx10f004b00", .data = &panasonic_vvx10f004b00 }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, dsi_of_match); static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi) { const struct panel_desc_dsi *desc; const struct of_device_id *id; int err; id = of_match_node(dsi_of_match, dsi->dev.of_node); if (!id) return -ENODEV; desc = id->data; err = panel_simple_probe(&dsi->dev, &desc->desc); if (err < 0) return err; dsi->mode_flags = desc->flags; dsi->format = desc->format; dsi->lanes = desc->lanes; return mipi_dsi_attach(dsi); } static int panel_simple_dsi_remove(struct mipi_dsi_device *dsi) { int err; err = mipi_dsi_detach(dsi); if (err < 0) dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err); return panel_simple_remove(&dsi->dev); } static void panel_simple_dsi_shutdown(struct mipi_dsi_device *dsi) { panel_simple_shutdown(&dsi->dev); } static struct mipi_dsi_driver panel_simple_dsi_driver = { .driver = { .name = "panel-simple-dsi", .owner = THIS_MODULE, .of_match_table = dsi_of_match, }, .probe = panel_simple_dsi_probe, .remove = panel_simple_dsi_remove, .shutdown = panel_simple_dsi_shutdown, }; static int __init panel_simple_init(void) { int err; err = platform_driver_register(&panel_simple_platform_driver); if (err < 0) return err; if (IS_ENABLED(CONFIG_DRM_MIPI_DSI)) { err = mipi_dsi_driver_register(&panel_simple_dsi_driver); if (err < 0) return err; } return 0; } module_init(panel_simple_init); static void __exit panel_simple_exit(void) { if (IS_ENABLED(CONFIG_DRM_MIPI_DSI)) mipi_dsi_driver_unregister(&panel_simple_dsi_driver); platform_driver_unregister(&panel_simple_platform_driver); } module_exit(panel_simple_exit); MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>"); MODULE_DESCRIPTION("DRM Driver for Simple Panels"); MODULE_LICENSE("GPL and additional rights");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
You can’t perform that action at this time.