diff options
author | Rob Clark <robdclark@chromium.org> | 2021-12-06 20:13:49 +0300 |
---|---|---|
committer | Rob Clark <robdclark@chromium.org> | 2021-12-06 20:14:28 +0300 |
commit | 83b965d118cbab1dbdfffdff8cabc8c1cfd183c6 (patch) | |
tree | f46a8f6d854b05a47311125f6fd6b6081e79557a /drivers/gpu/drm/tiny | |
parent | fee32807633395e666f0951d6b7b6546e9b76c3d (diff) | |
parent | c305ae99dfd4d0fe70c7fdf13ef5f7650a804ea7 (diff) | |
download | linux-83b965d118cbab1dbdfffdff8cabc8c1cfd183c6.tar.xz |
Merge remote-tracking branch 'drm/drm-next' into msm-next-staging
Backmerge drm-next to pull in:
8f59ee9a570c ("drm/msm/dsi: Adjust probe order")
Signed-off-by: Rob Clark <robdclark@chromium.org>
Diffstat (limited to 'drivers/gpu/drm/tiny')
-rw-r--r-- | drivers/gpu/drm/tiny/Kconfig | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/tiny/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/tiny/cirrus.c | 24 | ||||
-rw-r--r-- | drivers/gpu/drm/tiny/ili9163.c | 225 | ||||
-rw-r--r-- | drivers/gpu/drm/tiny/repaper.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/tiny/simpledrm.c | 37 | ||||
-rw-r--r-- | drivers/gpu/drm/tiny/st7586.c | 2 |
7 files changed, 282 insertions, 22 deletions
diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig index 1ceb93fbdc50..4ca309f80dee 100644 --- a/drivers/gpu/drm/tiny/Kconfig +++ b/drivers/gpu/drm/tiny/Kconfig @@ -80,6 +80,19 @@ config TINYDRM_HX8357D If M is selected the module will be called hx8357d. +config TINYDRM_ILI9163 + tristate "DRM support for ILI9163 display panels" + depends on DRM && SPI + select BACKLIGHT_CLASS_DEVICE + select DRM_KMS_CMA_HELPER + select DRM_KMS_HELPER + select DRM_MIPI_DBI + help + DRM driver for the following Ilitek ILI9163 panels: + * NHD-1.8-128160EF 128x160 TFT + + If M is selected the module will be called ili9163. + config TINYDRM_ILI9225 tristate "DRM support for ILI9225 display panels" depends on DRM && SPI diff --git a/drivers/gpu/drm/tiny/Makefile b/drivers/gpu/drm/tiny/Makefile index e09942895c77..5d5505d40e7b 100644 --- a/drivers/gpu/drm/tiny/Makefile +++ b/drivers/gpu/drm/tiny/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus.o obj-$(CONFIG_DRM_GM12U320) += gm12u320.o obj-$(CONFIG_DRM_SIMPLEDRM) += simpledrm.o obj-$(CONFIG_TINYDRM_HX8357D) += hx8357d.o +obj-$(CONFIG_TINYDRM_ILI9163) += ili9163.o obj-$(CONFIG_TINYDRM_ILI9225) += ili9225.o obj-$(CONFIG_TINYDRM_ILI9341) += ili9341.o obj-$(CONFIG_TINYDRM_ILI9486) += ili9486.o diff --git a/drivers/gpu/drm/tiny/cirrus.c b/drivers/gpu/drm/tiny/cirrus.c index 4611ec408506..9327001d35dd 100644 --- a/drivers/gpu/drm/tiny/cirrus.c +++ b/drivers/gpu/drm/tiny/cirrus.c @@ -317,28 +317,28 @@ static int cirrus_fb_blit_rect(struct drm_framebuffer *fb, const struct dma_buf_ struct drm_rect *rect) { struct cirrus_device *cirrus = to_cirrus(fb->dev); + void __iomem *dst = cirrus->vram; void *vmap = map->vaddr; /* TODO: Use mapping abstraction properly */ int idx; if (!drm_dev_enter(&cirrus->dev, &idx)) return -ENODEV; - if (cirrus->cpp == fb->format->cpp[0]) - drm_fb_memcpy_dstclip(cirrus->vram, fb->pitches[0], - vmap, fb, rect); + if (cirrus->cpp == fb->format->cpp[0]) { + dst += drm_fb_clip_offset(fb->pitches[0], fb->format, rect); + drm_fb_memcpy_toio(dst, fb->pitches[0], vmap, fb, rect); - else if (fb->format->cpp[0] == 4 && cirrus->cpp == 2) - drm_fb_xrgb8888_to_rgb565_dstclip(cirrus->vram, - cirrus->pitch, - vmap, fb, rect, false); + } else if (fb->format->cpp[0] == 4 && cirrus->cpp == 2) { + dst += drm_fb_clip_offset(cirrus->pitch, fb->format, rect); + drm_fb_xrgb8888_to_rgb565_toio(dst, cirrus->pitch, vmap, fb, rect, false); - else if (fb->format->cpp[0] == 4 && cirrus->cpp == 3) - drm_fb_xrgb8888_to_rgb888_dstclip(cirrus->vram, - cirrus->pitch, - vmap, fb, rect); + } else if (fb->format->cpp[0] == 4 && cirrus->cpp == 3) { + dst += drm_fb_clip_offset(cirrus->pitch, fb->format, rect); + drm_fb_xrgb8888_to_rgb888_toio(dst, cirrus->pitch, vmap, fb, rect); - else + } else { WARN_ON_ONCE("cpp mismatch"); + } drm_dev_exit(idx); diff --git a/drivers/gpu/drm/tiny/ili9163.c b/drivers/gpu/drm/tiny/ili9163.c new file mode 100644 index 000000000000..bcc181351236 --- /dev/null +++ b/drivers/gpu/drm/tiny/ili9163.c @@ -0,0 +1,225 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <linux/backlight.h> +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/module.h> +#include <linux/property.h> +#include <linux/spi/spi.h> + +#include <drm/drm_atomic_helper.h> +#include <drm/drm_drv.h> +#include <drm/drm_fb_helper.h> +#include <drm/drm_gem_atomic_helper.h> +#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_mipi_dbi.h> +#include <drm/drm_modeset_helper.h> + +#include <video/mipi_display.h> + +#define ILI9163_FRMCTR1 0xb1 + +#define ILI9163_PWCTRL1 0xc0 +#define ILI9163_PWCTRL2 0xc1 +#define ILI9163_VMCTRL1 0xc5 +#define ILI9163_VMCTRL2 0xc7 +#define ILI9163_PWCTRLA 0xcb +#define ILI9163_PWCTRLB 0xcf + +#define ILI9163_EN3GAM 0xf2 + +#define ILI9163_MADCTL_BGR BIT(3) +#define ILI9163_MADCTL_MV BIT(5) +#define ILI9163_MADCTL_MX BIT(6) +#define ILI9163_MADCTL_MY BIT(7) + +static void yx240qv29_enable(struct drm_simple_display_pipe *pipe, + struct drm_crtc_state *crtc_state, + struct drm_plane_state *plane_state) +{ + struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); + struct mipi_dbi *dbi = &dbidev->dbi; + u8 addr_mode; + int ret, idx; + + if (!drm_dev_enter(pipe->crtc.dev, &idx)) + return; + + DRM_DEBUG_KMS("\n"); + + ret = mipi_dbi_poweron_conditional_reset(dbidev); + if (ret < 0) + goto out_exit; + if (ret == 1) + goto out_enable; + + /* Gamma */ + mipi_dbi_command(dbi, MIPI_DCS_SET_GAMMA_CURVE, 0x04); + mipi_dbi_command(dbi, ILI9163_EN3GAM, 0x00); + + /* Frame Rate */ + mipi_dbi_command(dbi, ILI9163_FRMCTR1, 0x0a, 0x14); + + /* Power Control */ + mipi_dbi_command(dbi, ILI9163_PWCTRL1, 0x0a, 0x00); + mipi_dbi_command(dbi, ILI9163_PWCTRL2, 0x02); + + /* VCOM */ + mipi_dbi_command(dbi, ILI9163_VMCTRL1, 0x2f, 0x3e); + mipi_dbi_command(dbi, ILI9163_VMCTRL2, 0x40); + + /* Memory Access Control */ + mipi_dbi_command(dbi, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT); + + mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE); + msleep(100); + + mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON); + msleep(100); + +out_enable: + switch (dbidev->rotation) { + default: + addr_mode = ILI9163_MADCTL_MX | ILI9163_MADCTL_MY; + break; + case 90: + addr_mode = ILI9163_MADCTL_MX | ILI9163_MADCTL_MV; + break; + case 180: + addr_mode = 0; + break; + case 270: + addr_mode = ILI9163_MADCTL_MY | ILI9163_MADCTL_MV; + break; + } + addr_mode |= ILI9163_MADCTL_BGR; + mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); + mipi_dbi_enable_flush(dbidev, crtc_state, plane_state); +out_exit: + drm_dev_exit(idx); +} + +static const struct drm_simple_display_pipe_funcs ili9163_pipe_funcs = { + .enable = yx240qv29_enable, + .disable = mipi_dbi_pipe_disable, + .update = mipi_dbi_pipe_update, + .prepare_fb = drm_gem_simple_display_pipe_prepare_fb, +}; + +static const struct drm_display_mode yx240qv29_mode = { + DRM_SIMPLE_MODE(128, 160, 28, 35), +}; + +DEFINE_DRM_GEM_CMA_FOPS(ili9163_fops); + +static struct drm_driver ili9163_driver = { + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, + .fops = &ili9163_fops, + DRM_GEM_CMA_DRIVER_OPS_VMAP, + .debugfs_init = mipi_dbi_debugfs_init, + .name = "ili9163", + .desc = "Ilitek ILI9163", + .date = "20210208", + .major = 1, + .minor = 0, +}; + +static const struct of_device_id ili9163_of_match[] = { + { .compatible = "newhaven,1.8-128160EF" }, + { } +}; +MODULE_DEVICE_TABLE(of, ili9163_of_match); + +static const struct spi_device_id ili9163_id[] = { + { "nhd-1.8-128160EF", 0 }, + { } +}; +MODULE_DEVICE_TABLE(spi, ili9163_id); + +static int ili9163_probe(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + struct mipi_dbi_dev *dbidev; + struct drm_device *drm; + struct mipi_dbi *dbi; + struct gpio_desc *dc; + u32 rotation = 0; + int ret; + + dbidev = devm_drm_dev_alloc(dev, &ili9163_driver, + struct mipi_dbi_dev, drm); + if (IS_ERR(dbidev)) + return PTR_ERR(dbidev); + + dbi = &dbidev->dbi; + drm = &dbidev->drm; + + spi_set_drvdata(spi, drm); + + dbi->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(dbi->reset)) { + DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n"); + return PTR_ERR(dbi->reset); + } + + dc = devm_gpiod_get_optional(dev, "dc", GPIOD_OUT_LOW); + if (IS_ERR(dc)) { + DRM_DEV_ERROR(dev, "Failed to get gpio 'dc'\n"); + return PTR_ERR(dc); + } + + dbidev->backlight = devm_of_find_backlight(dev); + if (IS_ERR(dbidev->backlight)) + return PTR_ERR(dbidev->backlight); + + device_property_read_u32(dev, "rotation", &rotation); + + ret = mipi_dbi_spi_init(spi, dbi, dc); + if (ret) + return ret; + + ret = mipi_dbi_dev_init(dbidev, &ili9163_pipe_funcs, &yx240qv29_mode, rotation); + if (ret) + return ret; + + drm_mode_config_reset(drm); + + ret = drm_dev_register(drm, 0); + if (ret) + return ret; + + drm_fbdev_generic_setup(drm, 0); + + return 0; +} + +static int ili9163_remove(struct spi_device *spi) +{ + struct drm_device *drm = spi_get_drvdata(spi); + + drm_dev_unplug(drm); + drm_atomic_helper_shutdown(drm); + + return 0; +} + +static void ili9163_shutdown(struct spi_device *spi) +{ + drm_atomic_helper_shutdown(spi_get_drvdata(spi)); +} + +static struct spi_driver ili9163_spi_driver = { + .driver = { + .name = "ili9163", + .of_match_table = ili9163_of_match, + }, + .id_table = ili9163_id, + .probe = ili9163_probe, + .remove = ili9163_remove, + .shutdown = ili9163_shutdown, +}; +module_spi_driver(ili9163_spi_driver); + +MODULE_DESCRIPTION("Ilitek ILI9163 DRM driver"); +MODULE_AUTHOR("Daniel Mack <daniel@zonque.org>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c index 4d07b21a16e6..97a775c48cea 100644 --- a/drivers/gpu/drm/tiny/repaper.c +++ b/drivers/gpu/drm/tiny/repaper.c @@ -560,7 +560,7 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb) if (ret) goto out_free; - drm_fb_xrgb8888_to_gray8(buf, cma_obj->vaddr, fb, &clip); + drm_fb_xrgb8888_to_gray8(buf, 0, cma_obj->vaddr, fb, &clip); drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE); diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c index 481b48bde047..2f999915b9aa 100644 --- a/drivers/gpu/drm/tiny/simpledrm.c +++ b/drivers/gpu/drm/tiny/simpledrm.c @@ -2,6 +2,7 @@ #include <linux/clk.h> #include <linux/of_clk.h> +#include <linux/minmax.h> #include <linux/platform_data/simplefb.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> @@ -641,16 +642,25 @@ simpledrm_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, struct drm_framebuffer *fb = plane_state->fb; void *vmap = shadow_plane_state->data[0].vaddr; /* TODO: Use mapping abstraction */ struct drm_device *dev = &sdev->dev; + void __iomem *dst = sdev->screen_base; + struct drm_rect src_clip, dst_clip; int idx; if (!fb) return; + drm_rect_fp_to_int(&src_clip, &plane_state->src); + + dst_clip = plane_state->dst; + if (!drm_rect_intersect(&dst_clip, &src_clip)) + return; + if (!drm_dev_enter(dev, &idx)) return; - drm_fb_blit_dstclip(sdev->screen_base, sdev->pitch, - sdev->format->format, vmap, fb); + dst += drm_fb_clip_offset(sdev->pitch, sdev->format, &dst_clip); + drm_fb_blit_toio(dst, sdev->pitch, sdev->format->format, vmap, fb, &src_clip); + drm_dev_exit(idx); } @@ -680,20 +690,25 @@ simpledrm_simple_display_pipe_update(struct drm_simple_display_pipe *pipe, void *vmap = shadow_plane_state->data[0].vaddr; /* TODO: Use mapping abstraction */ struct drm_framebuffer *fb = plane_state->fb; struct drm_device *dev = &sdev->dev; - struct drm_rect clip; + void __iomem *dst = sdev->screen_base; + struct drm_rect src_clip, dst_clip; int idx; if (!fb) return; - if (!drm_atomic_helper_damage_merged(old_plane_state, plane_state, &clip)) + if (!drm_atomic_helper_damage_merged(old_plane_state, plane_state, &src_clip)) + return; + + dst_clip = plane_state->dst; + if (!drm_rect_intersect(&dst_clip, &src_clip)) return; if (!drm_dev_enter(dev, &idx)) return; - drm_fb_blit_rect_dstclip(sdev->screen_base, sdev->pitch, - sdev->format->format, vmap, fb, &clip); + dst += drm_fb_clip_offset(sdev->pitch, sdev->format, &dst_clip); + drm_fb_blit_toio(dst, sdev->pitch, sdev->format->format, vmap, fb, &src_clip); drm_dev_exit(idx); } @@ -758,6 +773,7 @@ static int simpledrm_device_init_modeset(struct simpledrm_device *sdev) struct drm_display_mode *mode = &sdev->mode; struct drm_connector *connector = &sdev->connector; struct drm_simple_display_pipe *pipe = &sdev->pipe; + unsigned long max_width, max_height; const uint32_t *formats; size_t nformats; int ret; @@ -766,10 +782,13 @@ static int simpledrm_device_init_modeset(struct simpledrm_device *sdev) if (ret) return ret; + max_width = max_t(unsigned long, mode->hdisplay, DRM_SHADOW_PLANE_MAX_WIDTH); + max_height = max_t(unsigned long, mode->vdisplay, DRM_SHADOW_PLANE_MAX_HEIGHT); + dev->mode_config.min_width = mode->hdisplay; - dev->mode_config.max_width = mode->hdisplay; + dev->mode_config.max_width = max_width; dev->mode_config.min_height = mode->vdisplay; - dev->mode_config.max_height = mode->vdisplay; + dev->mode_config.max_height = max_height; dev->mode_config.prefer_shadow_fbdev = true; dev->mode_config.preferred_depth = sdev->format->cpp[0] * 8; dev->mode_config.funcs = &simpledrm_mode_config_funcs; @@ -788,6 +807,8 @@ static int simpledrm_device_init_modeset(struct simpledrm_device *sdev) if (ret) return ret; + drm_plane_enable_fb_damage_clips(&pipe->plane); + drm_mode_config_reset(dev); return 0; diff --git a/drivers/gpu/drm/tiny/st7586.c b/drivers/gpu/drm/tiny/st7586.c index ad0faa8723c2..51b9b9fb3ead 100644 --- a/drivers/gpu/drm/tiny/st7586.c +++ b/drivers/gpu/drm/tiny/st7586.c @@ -73,7 +73,7 @@ static void st7586_xrgb8888_to_gray332(u8 *dst, void *vaddr, if (!buf) return; - drm_fb_xrgb8888_to_gray8(buf, vaddr, fb, clip); + drm_fb_xrgb8888_to_gray8(buf, 0, vaddr, fb, clip); src = buf; for (y = clip->y1; y < clip->y2; y++) { |