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

panel-abt-y030xx067a.c (9902B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Asia Better Technology Ltd. Y030XX067A IPS LCD panel driver
      4 *
      5 * Copyright (C) 2020, Paul Cercueil <paul@crapouillou.net>
      6 * Copyright (C) 2020, Christophe Branchereau <cbranchereau@gmail.com>
      7 */
      8
      9#include <linux/delay.h>
     10#include <linux/device.h>
     11#include <linux/gpio/consumer.h>
     12#include <linux/media-bus-format.h>
     13#include <linux/module.h>
     14#include <linux/of_device.h>
     15#include <linux/regmap.h>
     16#include <linux/regulator/consumer.h>
     17#include <linux/spi/spi.h>
     18
     19#include <drm/drm_modes.h>
     20#include <drm/drm_panel.h>
     21
     22#define REG00_VBRT_CTRL(val)		(val)
     23
     24#define REG01_COM_DC(val)		(val)
     25
     26#define REG02_DA_CONTRAST(val)		(val)
     27#define REG02_VESA_SEL(val)		((val) << 5)
     28#define REG02_COMDC_SW			BIT(7)
     29
     30#define REG03_VPOSITION(val)		(val)
     31#define REG03_BSMOUNT			BIT(5)
     32#define REG03_COMTST			BIT(6)
     33#define REG03_HPOSITION1		BIT(7)
     34
     35#define REG04_HPOSITION1(val)		(val)
     36
     37#define REG05_CLIP			BIT(0)
     38#define REG05_NVM_VREFRESH		BIT(1)
     39#define REG05_SLFR			BIT(2)
     40#define REG05_SLBRCHARGE(val)		((val) << 3)
     41#define REG05_PRECHARGE_LEVEL(val)	((val) << 6)
     42
     43#define REG06_TEST5			BIT(0)
     44#define REG06_SLDWN			BIT(1)
     45#define REG06_SLRGT			BIT(2)
     46#define REG06_TEST2			BIT(3)
     47#define REG06_XPSAVE			BIT(4)
     48#define REG06_GAMMA_SEL(val)		((val) << 5)
     49#define REG06_NT			BIT(7)
     50
     51#define REG07_TEST1			BIT(0)
     52#define REG07_HDVD_POL			BIT(1)
     53#define REG07_CK_POL			BIT(2)
     54#define REG07_TEST3			BIT(3)
     55#define REG07_TEST4			BIT(4)
     56#define REG07_480_LINEMASK		BIT(5)
     57#define REG07_AMPTST(val)		((val) << 6)
     58
     59#define REG08_SLHRC(val)		(val)
     60#define REG08_CLOCK_DIV(val)		((val) << 2)
     61#define REG08_PANEL(val)		((val) << 5)
     62
     63#define REG09_SUB_BRIGHT_R(val)		(val)
     64#define REG09_NW_NB			BIT(6)
     65#define REG09_IPCON			BIT(7)
     66
     67#define REG0A_SUB_BRIGHT_B(val)		(val)
     68#define REG0A_PAIR			BIT(6)
     69#define REG0A_DE_SEL			BIT(7)
     70
     71#define REG0B_MBK_POSITION(val)		(val)
     72#define REG0B_HD_FREERUN		BIT(4)
     73#define REG0B_VD_FREERUN		BIT(5)
     74#define REG0B_YUV2BIN(val)		((val) << 6)
     75
     76#define REG0C_CONTRAST_R(val)		(val)
     77#define REG0C_DOUBLEREAD		BIT(7)
     78
     79#define REG0D_CONTRAST_G(val)		(val)
     80#define REG0D_RGB_YUV			BIT(7)
     81
     82#define REG0E_CONTRAST_B(val)		(val)
     83#define REG0E_PIXELCOLORDRIVE		BIT(7)
     84
     85#define REG0F_ASPECT			BIT(0)
     86#define REG0F_OVERSCAN(val)		((val) << 1)
     87#define REG0F_FRAMEWIDTH(val)		((val) << 3)
     88
     89#define REG10_BRIGHT(val)		(val)
     90
     91#define REG11_SIG_GAIN(val)		(val)
     92#define REG11_SIGC_CNTL			BIT(6)
     93#define REG11_SIGC_POL			BIT(7)
     94
     95#define REG12_COLOR(val)		(val)
     96#define REG12_PWCKSEL(val)		((val) << 6)
     97
     98#define REG13_4096LEVEL_CNTL(val)	(val)
     99#define REG13_SL4096(val)		((val) << 4)
    100#define REG13_LIMITER_CONTROL		BIT(7)
    101
    102#define REG14_PANEL_TEST(val)		(val)
    103
    104#define REG15_NVM_LINK0			BIT(0)
    105#define REG15_NVM_LINK1			BIT(1)
    106#define REG15_NVM_LINK2			BIT(2)
    107#define REG15_NVM_LINK3			BIT(3)
    108#define REG15_NVM_LINK4			BIT(4)
    109#define REG15_NVM_LINK5			BIT(5)
    110#define REG15_NVM_LINK6			BIT(6)
    111#define REG15_NVM_LINK7			BIT(7)
    112
    113struct y030xx067a_info {
    114	const struct drm_display_mode *display_modes;
    115	unsigned int num_modes;
    116	u16 width_mm, height_mm;
    117	u32 bus_format, bus_flags;
    118};
    119
    120struct y030xx067a {
    121	struct drm_panel panel;
    122	struct spi_device *spi;
    123	struct regmap *map;
    124
    125	const struct y030xx067a_info *panel_info;
    126
    127	struct regulator *supply;
    128	struct gpio_desc *reset_gpio;
    129};
    130
    131static inline struct y030xx067a *to_y030xx067a(struct drm_panel *panel)
    132{
    133	return container_of(panel, struct y030xx067a, panel);
    134}
    135
    136static const struct reg_sequence y030xx067a_init_sequence[] = {
    137	{ 0x00, REG00_VBRT_CTRL(0x7f) },
    138	{ 0x01, REG01_COM_DC(0x3c) },
    139	{ 0x02, REG02_VESA_SEL(0x3) | REG02_DA_CONTRAST(0x1f) },
    140	{ 0x03, REG03_VPOSITION(0x0a) },
    141	{ 0x04, REG04_HPOSITION1(0xd2) },
    142	{ 0x05, REG05_CLIP | REG05_NVM_VREFRESH | REG05_SLBRCHARGE(0x2) },
    143	{ 0x06, REG06_NT },
    144	{ 0x07, 0 },
    145	{ 0x08, REG08_PANEL(0x1) | REG08_CLOCK_DIV(0x2) },
    146	{ 0x09, REG09_SUB_BRIGHT_R(0x20) },
    147	{ 0x0a, REG0A_SUB_BRIGHT_B(0x20) },
    148	{ 0x0b, REG0B_HD_FREERUN | REG0B_VD_FREERUN },
    149	{ 0x0c, REG0C_CONTRAST_R(0x00) },
    150	{ 0x0d, REG0D_CONTRAST_G(0x00) },
    151	{ 0x0e, REG0E_CONTRAST_B(0x10) },
    152	{ 0x0f, 0 },
    153	{ 0x10, REG10_BRIGHT(0x7f) },
    154	{ 0x11, REG11_SIGC_CNTL | REG11_SIG_GAIN(0x3f) },
    155	{ 0x12, REG12_COLOR(0x20) | REG12_PWCKSEL(0x1) },
    156	{ 0x13, REG13_4096LEVEL_CNTL(0x8) },
    157	{ 0x14, 0 },
    158	{ 0x15, 0 },
    159};
    160
    161static int y030xx067a_prepare(struct drm_panel *panel)
    162{
    163	struct y030xx067a *priv = to_y030xx067a(panel);
    164	struct device *dev = &priv->spi->dev;
    165	int err;
    166
    167	err = regulator_enable(priv->supply);
    168	if (err) {
    169		dev_err(dev, "Failed to enable power supply: %d\n", err);
    170		return err;
    171	}
    172
    173	/* Reset the chip */
    174	gpiod_set_value_cansleep(priv->reset_gpio, 1);
    175	usleep_range(1000, 20000);
    176	gpiod_set_value_cansleep(priv->reset_gpio, 0);
    177	usleep_range(1000, 20000);
    178
    179	err = regmap_multi_reg_write(priv->map, y030xx067a_init_sequence,
    180				     ARRAY_SIZE(y030xx067a_init_sequence));
    181	if (err) {
    182		dev_err(dev, "Failed to init registers: %d\n", err);
    183		goto err_disable_regulator;
    184	}
    185
    186	return 0;
    187
    188err_disable_regulator:
    189	regulator_disable(priv->supply);
    190	return err;
    191}
    192
    193static int y030xx067a_unprepare(struct drm_panel *panel)
    194{
    195	struct y030xx067a *priv = to_y030xx067a(panel);
    196
    197	gpiod_set_value_cansleep(priv->reset_gpio, 1);
    198	regulator_disable(priv->supply);
    199
    200	return 0;
    201}
    202
    203static int y030xx067a_enable(struct drm_panel *panel)
    204{
    205	struct y030xx067a *priv = to_y030xx067a(panel);
    206
    207	regmap_set_bits(priv->map, 0x06, REG06_XPSAVE);
    208
    209	if (panel->backlight) {
    210		/* Wait for the picture to be ready before enabling backlight */
    211		msleep(120);
    212	}
    213
    214	return 0;
    215}
    216
    217static int y030xx067a_disable(struct drm_panel *panel)
    218{
    219	struct y030xx067a *priv = to_y030xx067a(panel);
    220
    221	regmap_clear_bits(priv->map, 0x06, REG06_XPSAVE);
    222
    223	return 0;
    224}
    225
    226static int y030xx067a_get_modes(struct drm_panel *panel,
    227				struct drm_connector *connector)
    228{
    229	struct y030xx067a *priv = to_y030xx067a(panel);
    230	const struct y030xx067a_info *panel_info = priv->panel_info;
    231	struct drm_display_mode *mode;
    232	unsigned int i;
    233
    234	for (i = 0; i < panel_info->num_modes; i++) {
    235		mode = drm_mode_duplicate(connector->dev,
    236					  &panel_info->display_modes[i]);
    237		if (!mode)
    238			return -ENOMEM;
    239
    240		drm_mode_set_name(mode);
    241
    242		mode->type = DRM_MODE_TYPE_DRIVER;
    243		if (panel_info->num_modes == 1)
    244			mode->type |= DRM_MODE_TYPE_PREFERRED;
    245
    246		drm_mode_probed_add(connector, mode);
    247	}
    248
    249	connector->display_info.bpc = 8;
    250	connector->display_info.width_mm = panel_info->width_mm;
    251	connector->display_info.height_mm = panel_info->height_mm;
    252
    253	drm_display_info_set_bus_formats(&connector->display_info,
    254					 &panel_info->bus_format, 1);
    255	connector->display_info.bus_flags = panel_info->bus_flags;
    256
    257	return panel_info->num_modes;
    258}
    259
    260static const struct drm_panel_funcs y030xx067a_funcs = {
    261	.prepare	= y030xx067a_prepare,
    262	.unprepare	= y030xx067a_unprepare,
    263	.enable		= y030xx067a_enable,
    264	.disable	= y030xx067a_disable,
    265	.get_modes	= y030xx067a_get_modes,
    266};
    267
    268static const struct regmap_config y030xx067a_regmap_config = {
    269	.reg_bits = 8,
    270	.val_bits = 8,
    271	.max_register = 0x15,
    272	.cache_type = REGCACHE_FLAT,
    273};
    274
    275static int y030xx067a_probe(struct spi_device *spi)
    276{
    277	struct device *dev = &spi->dev;
    278	struct y030xx067a *priv;
    279	int err;
    280
    281	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
    282	if (!priv)
    283		return -ENOMEM;
    284
    285	priv->spi = spi;
    286	spi_set_drvdata(spi, priv);
    287
    288	priv->map = devm_regmap_init_spi(spi, &y030xx067a_regmap_config);
    289	if (IS_ERR(priv->map)) {
    290		dev_err(dev, "Unable to init regmap\n");
    291		return PTR_ERR(priv->map);
    292	}
    293
    294	priv->panel_info = of_device_get_match_data(dev);
    295	if (!priv->panel_info)
    296		return -EINVAL;
    297
    298	priv->supply = devm_regulator_get(dev, "power");
    299	if (IS_ERR(priv->supply))
    300		return dev_err_probe(dev, PTR_ERR(priv->supply),
    301				     "Failed to get power supply\n");
    302
    303	priv->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
    304	if (IS_ERR(priv->reset_gpio))
    305		return dev_err_probe(dev, PTR_ERR(priv->reset_gpio),
    306				     "Failed to get reset GPIO\n");
    307
    308	drm_panel_init(&priv->panel, dev, &y030xx067a_funcs,
    309		       DRM_MODE_CONNECTOR_DPI);
    310
    311	err = drm_panel_of_backlight(&priv->panel);
    312	if (err)
    313		return err;
    314
    315	drm_panel_add(&priv->panel);
    316
    317	return 0;
    318}
    319
    320static void y030xx067a_remove(struct spi_device *spi)
    321{
    322	struct y030xx067a *priv = spi_get_drvdata(spi);
    323
    324	drm_panel_remove(&priv->panel);
    325	drm_panel_disable(&priv->panel);
    326	drm_panel_unprepare(&priv->panel);
    327}
    328
    329static const struct drm_display_mode y030xx067a_modes[] = {
    330	{ /* 60 Hz */
    331		.clock = 14400,
    332		.hdisplay = 320,
    333		.hsync_start = 320 + 10,
    334		.hsync_end = 320 + 10 + 37,
    335		.htotal = 320 + 10 + 37 + 33,
    336		.vdisplay = 480,
    337		.vsync_start = 480 + 84,
    338		.vsync_end = 480 + 84 + 20,
    339		.vtotal = 480 + 84 + 20 + 16,
    340		.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
    341	},
    342	{ /* 50 Hz */
    343		.clock = 12000,
    344		.hdisplay = 320,
    345		.hsync_start = 320 + 10,
    346		.hsync_end = 320 + 10 + 37,
    347		.htotal = 320 + 10 + 37 + 33,
    348		.vdisplay = 480,
    349		.vsync_start = 480 + 84,
    350		.vsync_end = 480 + 84 + 20,
    351		.vtotal = 480 + 84 + 20 + 16,
    352		.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
    353	},
    354};
    355
    356static const struct y030xx067a_info y030xx067a_info = {
    357	.display_modes = y030xx067a_modes,
    358	.num_modes = ARRAY_SIZE(y030xx067a_modes),
    359	.width_mm = 69,
    360	.height_mm = 51,
    361	.bus_format = MEDIA_BUS_FMT_RGB888_3X8_DELTA,
    362	.bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE | DRM_BUS_FLAG_DE_LOW,
    363};
    364
    365static const struct of_device_id y030xx067a_of_match[] = {
    366	{ .compatible = "abt,y030xx067a", .data = &y030xx067a_info },
    367	{ /* sentinel */ }
    368};
    369MODULE_DEVICE_TABLE(of, y030xx067a_of_match);
    370
    371static struct spi_driver y030xx067a_driver = {
    372	.driver = {
    373		.name = "abt-y030xx067a",
    374		.of_match_table = y030xx067a_of_match,
    375	},
    376	.probe = y030xx067a_probe,
    377	.remove = y030xx067a_remove,
    378};
    379module_spi_driver(y030xx067a_driver);
    380
    381MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
    382MODULE_AUTHOR("Christophe Branchereau <cbranchereau@gmail.com>");
    383MODULE_LICENSE("GPL v2");