cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ili9163.c (5347B)


      1// SPDX-License-Identifier: GPL-2.0+
      2
      3#include <linux/backlight.h>
      4#include <linux/delay.h>
      5#include <linux/gpio/consumer.h>
      6#include <linux/module.h>
      7#include <linux/property.h>
      8#include <linux/spi/spi.h>
      9
     10#include <drm/drm_atomic_helper.h>
     11#include <drm/drm_drv.h>
     12#include <drm/drm_fb_helper.h>
     13#include <drm/drm_gem_atomic_helper.h>
     14#include <drm/drm_gem_cma_helper.h>
     15#include <drm/drm_mipi_dbi.h>
     16#include <drm/drm_modeset_helper.h>
     17
     18#include <video/mipi_display.h>
     19
     20#define ILI9163_FRMCTR1		0xb1
     21
     22#define ILI9163_PWCTRL1		0xc0
     23#define ILI9163_PWCTRL2		0xc1
     24#define ILI9163_VMCTRL1		0xc5
     25#define ILI9163_VMCTRL2		0xc7
     26#define ILI9163_PWCTRLA		0xcb
     27#define ILI9163_PWCTRLB		0xcf
     28
     29#define ILI9163_EN3GAM		0xf2
     30
     31#define ILI9163_MADCTL_BGR	BIT(3)
     32#define ILI9163_MADCTL_MV	BIT(5)
     33#define ILI9163_MADCTL_MX	BIT(6)
     34#define ILI9163_MADCTL_MY	BIT(7)
     35
     36static void yx240qv29_enable(struct drm_simple_display_pipe *pipe,
     37			     struct drm_crtc_state *crtc_state,
     38			     struct drm_plane_state *plane_state)
     39{
     40	struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
     41	struct mipi_dbi *dbi = &dbidev->dbi;
     42	u8 addr_mode;
     43	int ret, idx;
     44
     45	if (!drm_dev_enter(pipe->crtc.dev, &idx))
     46		return;
     47
     48	DRM_DEBUG_KMS("\n");
     49
     50	ret = mipi_dbi_poweron_conditional_reset(dbidev);
     51	if (ret < 0)
     52		goto out_exit;
     53	if (ret == 1)
     54		goto out_enable;
     55
     56	/* Gamma */
     57	mipi_dbi_command(dbi, MIPI_DCS_SET_GAMMA_CURVE, 0x04);
     58	mipi_dbi_command(dbi, ILI9163_EN3GAM, 0x00);
     59
     60	/* Frame Rate */
     61	mipi_dbi_command(dbi, ILI9163_FRMCTR1, 0x0a, 0x14);
     62
     63	/* Power Control */
     64	mipi_dbi_command(dbi, ILI9163_PWCTRL1, 0x0a, 0x00);
     65	mipi_dbi_command(dbi, ILI9163_PWCTRL2, 0x02);
     66
     67	/* VCOM */
     68	mipi_dbi_command(dbi, ILI9163_VMCTRL1, 0x2f, 0x3e);
     69	mipi_dbi_command(dbi, ILI9163_VMCTRL2, 0x40);
     70
     71	/* Memory Access Control */
     72	mipi_dbi_command(dbi, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT);
     73
     74	mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
     75	msleep(100);
     76
     77	mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
     78	msleep(100);
     79
     80out_enable:
     81	switch (dbidev->rotation) {
     82	default:
     83		addr_mode = ILI9163_MADCTL_MX | ILI9163_MADCTL_MY;
     84		break;
     85	case 90:
     86		addr_mode = ILI9163_MADCTL_MX | ILI9163_MADCTL_MV;
     87		break;
     88	case 180:
     89		addr_mode = 0;
     90		break;
     91	case 270:
     92		addr_mode = ILI9163_MADCTL_MY | ILI9163_MADCTL_MV;
     93		break;
     94	}
     95	addr_mode |= ILI9163_MADCTL_BGR;
     96	mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
     97	mipi_dbi_enable_flush(dbidev, crtc_state, plane_state);
     98out_exit:
     99	drm_dev_exit(idx);
    100}
    101
    102static const struct drm_simple_display_pipe_funcs ili9163_pipe_funcs = {
    103	.enable = yx240qv29_enable,
    104	.disable = mipi_dbi_pipe_disable,
    105	.update = mipi_dbi_pipe_update,
    106	.prepare_fb = drm_gem_simple_display_pipe_prepare_fb,
    107};
    108
    109static const struct drm_display_mode yx240qv29_mode = {
    110	DRM_SIMPLE_MODE(128, 160, 28, 35),
    111};
    112
    113DEFINE_DRM_GEM_CMA_FOPS(ili9163_fops);
    114
    115static struct drm_driver ili9163_driver = {
    116	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
    117	.fops			= &ili9163_fops,
    118	DRM_GEM_CMA_DRIVER_OPS_VMAP,
    119	.debugfs_init		= mipi_dbi_debugfs_init,
    120	.name			= "ili9163",
    121	.desc			= "Ilitek ILI9163",
    122	.date			= "20210208",
    123	.major			= 1,
    124	.minor			= 0,
    125};
    126
    127static const struct of_device_id ili9163_of_match[] = {
    128	{ .compatible = "newhaven,1.8-128160EF" },
    129	{ }
    130};
    131MODULE_DEVICE_TABLE(of, ili9163_of_match);
    132
    133static const struct spi_device_id ili9163_id[] = {
    134	{ "nhd-1.8-128160EF", 0 },
    135	{ }
    136};
    137MODULE_DEVICE_TABLE(spi, ili9163_id);
    138
    139static int ili9163_probe(struct spi_device *spi)
    140{
    141	struct device *dev = &spi->dev;
    142	struct mipi_dbi_dev *dbidev;
    143	struct drm_device *drm;
    144	struct mipi_dbi *dbi;
    145	struct gpio_desc *dc;
    146	u32 rotation = 0;
    147	int ret;
    148
    149	dbidev = devm_drm_dev_alloc(dev, &ili9163_driver,
    150				    struct mipi_dbi_dev, drm);
    151	if (IS_ERR(dbidev))
    152		return PTR_ERR(dbidev);
    153
    154	dbi = &dbidev->dbi;
    155	drm = &dbidev->drm;
    156
    157	spi_set_drvdata(spi, drm);
    158
    159	dbi->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
    160	if (IS_ERR(dbi->reset)) {
    161		DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n");
    162		return PTR_ERR(dbi->reset);
    163	}
    164
    165	dc = devm_gpiod_get_optional(dev, "dc", GPIOD_OUT_LOW);
    166	if (IS_ERR(dc)) {
    167		DRM_DEV_ERROR(dev, "Failed to get gpio 'dc'\n");
    168		return PTR_ERR(dc);
    169	}
    170
    171	dbidev->backlight = devm_of_find_backlight(dev);
    172	if (IS_ERR(dbidev->backlight))
    173		return PTR_ERR(dbidev->backlight);
    174
    175	device_property_read_u32(dev, "rotation", &rotation);
    176
    177	ret = mipi_dbi_spi_init(spi, dbi, dc);
    178	if (ret)
    179		return ret;
    180
    181	ret = mipi_dbi_dev_init(dbidev, &ili9163_pipe_funcs, &yx240qv29_mode, rotation);
    182	if (ret)
    183		return ret;
    184
    185	drm_mode_config_reset(drm);
    186
    187	ret = drm_dev_register(drm, 0);
    188	if (ret)
    189		return ret;
    190
    191	drm_fbdev_generic_setup(drm, 0);
    192
    193	return 0;
    194}
    195
    196static void ili9163_remove(struct spi_device *spi)
    197{
    198	struct drm_device *drm = spi_get_drvdata(spi);
    199
    200	drm_dev_unplug(drm);
    201	drm_atomic_helper_shutdown(drm);
    202}
    203
    204static void ili9163_shutdown(struct spi_device *spi)
    205{
    206	drm_atomic_helper_shutdown(spi_get_drvdata(spi));
    207}
    208
    209static struct spi_driver ili9163_spi_driver = {
    210	.driver = {
    211		.name = "ili9163",
    212		.of_match_table = ili9163_of_match,
    213	},
    214	.id_table = ili9163_id,
    215	.probe = ili9163_probe,
    216	.remove = ili9163_remove,
    217	.shutdown = ili9163_shutdown,
    218};
    219module_spi_driver(ili9163_spi_driver);
    220
    221MODULE_DESCRIPTION("Ilitek ILI9163 DRM driver");
    222MODULE_AUTHOR("Daniel Mack <daniel@zonque.org>");
    223MODULE_LICENSE("GPL");