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-novatek-nt35560.c (13826B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * MIPI-DSI Novatek NT35560-based panel controller.
      4 *
      5 * Supported panels include:
      6 * Sony ACX424AKM - a 480x854 AMOLED DSI panel
      7 * Sony ACX424AKP - a 480x864 AMOLED DSI panel
      8 *
      9 * Copyright (C) Linaro Ltd. 2019-2021
     10 * Author: Linus Walleij
     11 * Based on code and know-how from Marcus Lorentzon
     12 * Copyright (C) ST-Ericsson SA 2010
     13 * Based on code and know-how from Johan Olson and Joakim Wesslen
     14 * Copyright (C) Sony Ericsson Mobile Communications 2010
     15 */
     16#include <linux/backlight.h>
     17#include <linux/delay.h>
     18#include <linux/gpio/consumer.h>
     19#include <linux/module.h>
     20#include <linux/of.h>
     21#include <linux/of_device.h>
     22#include <linux/regulator/consumer.h>
     23
     24#include <video/mipi_display.h>
     25
     26#include <drm/drm_mipi_dsi.h>
     27#include <drm/drm_modes.h>
     28#include <drm/drm_panel.h>
     29
     30#define NT35560_DCS_READ_ID1		0xDA
     31#define NT35560_DCS_READ_ID2		0xDB
     32#define NT35560_DCS_READ_ID3		0xDC
     33#define NT35560_DCS_SET_MDDI		0xAE
     34
     35/*
     36 * Sony seems to use vendor ID 0x81
     37 */
     38#define DISPLAY_SONY_ACX424AKP_ID1	0x8103
     39#define DISPLAY_SONY_ACX424AKP_ID2	0x811a
     40#define DISPLAY_SONY_ACX424AKP_ID3	0x811b
     41/*
     42 * The fourth ID looks like a bug, vendor IDs begin at 0x80
     43 * and panel 00 ... seems like default values.
     44 */
     45#define DISPLAY_SONY_ACX424AKP_ID4	0x8000
     46
     47struct nt35560_config {
     48	const struct drm_display_mode *vid_mode;
     49	const struct drm_display_mode *cmd_mode;
     50};
     51
     52struct nt35560 {
     53	const struct nt35560_config *conf;
     54	struct drm_panel panel;
     55	struct device *dev;
     56	struct regulator *supply;
     57	struct gpio_desc *reset_gpio;
     58	bool video_mode;
     59};
     60
     61static const struct drm_display_mode sony_acx424akp_vid_mode = {
     62	.clock = 27234,
     63	.hdisplay = 480,
     64	.hsync_start = 480 + 15,
     65	.hsync_end = 480 + 15 + 0,
     66	.htotal = 480 + 15 + 0 + 15,
     67	.vdisplay = 864,
     68	.vsync_start = 864 + 14,
     69	.vsync_end = 864 + 14 + 1,
     70	.vtotal = 864 + 14 + 1 + 11,
     71	.width_mm = 48,
     72	.height_mm = 84,
     73	.flags = DRM_MODE_FLAG_PVSYNC,
     74};
     75
     76/*
     77 * The timings are not very helpful as the display is used in
     78 * command mode using the maximum HS frequency.
     79 */
     80static const struct drm_display_mode sony_acx424akp_cmd_mode = {
     81	.clock = 35478,
     82	.hdisplay = 480,
     83	.hsync_start = 480 + 154,
     84	.hsync_end = 480 + 154 + 16,
     85	.htotal = 480 + 154 + 16 + 32,
     86	.vdisplay = 864,
     87	.vsync_start = 864 + 1,
     88	.vsync_end = 864 + 1 + 1,
     89	.vtotal = 864 + 1 + 1 + 1,
     90	/*
     91	 * Some desired refresh rate, experiments at the maximum "pixel"
     92	 * clock speed (HS clock 420 MHz) yields around 117Hz.
     93	 */
     94	.width_mm = 48,
     95	.height_mm = 84,
     96};
     97
     98static const struct nt35560_config sony_acx424akp_data = {
     99	.vid_mode = &sony_acx424akp_vid_mode,
    100	.cmd_mode = &sony_acx424akp_cmd_mode,
    101};
    102
    103static const struct drm_display_mode sony_acx424akm_vid_mode = {
    104	.clock = 27234,
    105	.hdisplay = 480,
    106	.hsync_start = 480 + 15,
    107	.hsync_end = 480 + 15 + 0,
    108	.htotal = 480 + 15 + 0 + 15,
    109	.vdisplay = 854,
    110	.vsync_start = 854 + 14,
    111	.vsync_end = 854 + 14 + 1,
    112	.vtotal = 854 + 14 + 1 + 11,
    113	.width_mm = 46,
    114	.height_mm = 82,
    115	.flags = DRM_MODE_FLAG_PVSYNC,
    116};
    117
    118/*
    119 * The timings are not very helpful as the display is used in
    120 * command mode using the maximum HS frequency.
    121 */
    122static const struct drm_display_mode sony_acx424akm_cmd_mode = {
    123	.clock = 35478,
    124	.hdisplay = 480,
    125	.hsync_start = 480 + 154,
    126	.hsync_end = 480 + 154 + 16,
    127	.htotal = 480 + 154 + 16 + 32,
    128	.vdisplay = 854,
    129	.vsync_start = 854 + 1,
    130	.vsync_end = 854 + 1 + 1,
    131	.vtotal = 854 + 1 + 1 + 1,
    132	.width_mm = 46,
    133	.height_mm = 82,
    134};
    135
    136static const struct nt35560_config sony_acx424akm_data = {
    137	.vid_mode = &sony_acx424akm_vid_mode,
    138	.cmd_mode = &sony_acx424akm_cmd_mode,
    139};
    140
    141static inline struct nt35560 *panel_to_nt35560(struct drm_panel *panel)
    142{
    143	return container_of(panel, struct nt35560, panel);
    144}
    145
    146#define FOSC			20 /* 20Mhz */
    147#define SCALE_FACTOR_NS_DIV_MHZ	1000
    148
    149static int nt35560_set_brightness(struct backlight_device *bl)
    150{
    151	struct nt35560 *nt = bl_get_data(bl);
    152	struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
    153	int period_ns = 1023;
    154	int duty_ns = bl->props.brightness;
    155	u8 pwm_ratio;
    156	u8 pwm_div;
    157	u8 par;
    158	int ret;
    159
    160	if (backlight_is_blank(bl)) {
    161		/* Disable backlight */
    162		par = 0x00;
    163		ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY,
    164					 &par, 1);
    165		if (ret) {
    166			dev_err(nt->dev, "failed to disable display backlight (%d)\n", ret);
    167			return ret;
    168		}
    169		return 0;
    170	}
    171
    172	/* Calculate the PWM duty cycle in n/256's */
    173	pwm_ratio = max(((duty_ns * 256) / period_ns) - 1, 1);
    174	pwm_div = max(1,
    175		      ((FOSC * period_ns) / 256) /
    176		      SCALE_FACTOR_NS_DIV_MHZ);
    177
    178	/* Set up PWM dutycycle ONE byte (differs from the standard) */
    179	dev_dbg(nt->dev, "calculated duty cycle %02x\n", pwm_ratio);
    180	ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
    181				 &pwm_ratio, 1);
    182	if (ret < 0) {
    183		dev_err(nt->dev, "failed to set display PWM ratio (%d)\n", ret);
    184		return ret;
    185	}
    186
    187	/*
    188	 * Sequence to write PWMDIV:
    189	 *	address		data
    190	 *	0xF3		0xAA   CMD2 Unlock
    191	 *	0x00		0x01   Enter CMD2 page 0
    192	 *	0X7D		0x01   No reload MTP of CMD2 P1
    193	 *	0x22		PWMDIV
    194	 *	0x7F		0xAA   CMD2 page 1 lock
    195	 */
    196	par = 0xaa;
    197	ret = mipi_dsi_dcs_write(dsi, 0xf3, &par, 1);
    198	if (ret < 0) {
    199		dev_err(nt->dev, "failed to unlock CMD 2 (%d)\n", ret);
    200		return ret;
    201	}
    202	par = 0x01;
    203	ret = mipi_dsi_dcs_write(dsi, 0x00, &par, 1);
    204	if (ret < 0) {
    205		dev_err(nt->dev, "failed to enter page 1 (%d)\n", ret);
    206		return ret;
    207	}
    208	par = 0x01;
    209	ret = mipi_dsi_dcs_write(dsi, 0x7d, &par, 1);
    210	if (ret < 0) {
    211		dev_err(nt->dev, "failed to disable MTP reload (%d)\n", ret);
    212		return ret;
    213	}
    214	ret = mipi_dsi_dcs_write(dsi, 0x22, &pwm_div, 1);
    215	if (ret < 0) {
    216		dev_err(nt->dev, "failed to set PWM divisor (%d)\n", ret);
    217		return ret;
    218	}
    219	par = 0xaa;
    220	ret = mipi_dsi_dcs_write(dsi, 0x7f, &par, 1);
    221	if (ret < 0) {
    222		dev_err(nt->dev, "failed to lock CMD 2 (%d)\n", ret);
    223		return ret;
    224	}
    225
    226	/* Enable backlight */
    227	par = 0x24;
    228	ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY,
    229				 &par, 1);
    230	if (ret < 0) {
    231		dev_err(nt->dev, "failed to enable display backlight (%d)\n", ret);
    232		return ret;
    233	}
    234
    235	return 0;
    236}
    237
    238static const struct backlight_ops nt35560_bl_ops = {
    239	.update_status = nt35560_set_brightness,
    240};
    241
    242static const struct backlight_properties nt35560_bl_props = {
    243	.type = BACKLIGHT_RAW,
    244	.brightness = 512,
    245	.max_brightness = 1023,
    246};
    247
    248static int nt35560_read_id(struct nt35560 *nt)
    249{
    250	struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
    251	u8 vendor, version, panel;
    252	u16 val;
    253	int ret;
    254
    255	ret = mipi_dsi_dcs_read(dsi, NT35560_DCS_READ_ID1, &vendor, 1);
    256	if (ret < 0) {
    257		dev_err(nt->dev, "could not vendor ID byte\n");
    258		return ret;
    259	}
    260	ret = mipi_dsi_dcs_read(dsi, NT35560_DCS_READ_ID2, &version, 1);
    261	if (ret < 0) {
    262		dev_err(nt->dev, "could not read device version byte\n");
    263		return ret;
    264	}
    265	ret = mipi_dsi_dcs_read(dsi, NT35560_DCS_READ_ID3, &panel, 1);
    266	if (ret < 0) {
    267		dev_err(nt->dev, "could not read panel ID byte\n");
    268		return ret;
    269	}
    270
    271	if (vendor == 0x00) {
    272		dev_err(nt->dev, "device vendor ID is zero\n");
    273		return -ENODEV;
    274	}
    275
    276	val = (vendor << 8) | panel;
    277	switch (val) {
    278	case DISPLAY_SONY_ACX424AKP_ID1:
    279	case DISPLAY_SONY_ACX424AKP_ID2:
    280	case DISPLAY_SONY_ACX424AKP_ID3:
    281	case DISPLAY_SONY_ACX424AKP_ID4:
    282		dev_info(nt->dev, "MTP vendor: %02x, version: %02x, panel: %02x\n",
    283			 vendor, version, panel);
    284		break;
    285	default:
    286		dev_info(nt->dev, "unknown vendor: %02x, version: %02x, panel: %02x\n",
    287			 vendor, version, panel);
    288		break;
    289	}
    290
    291	return 0;
    292}
    293
    294static int nt35560_power_on(struct nt35560 *nt)
    295{
    296	int ret;
    297
    298	ret = regulator_enable(nt->supply);
    299	if (ret) {
    300		dev_err(nt->dev, "failed to enable supply (%d)\n", ret);
    301		return ret;
    302	}
    303
    304	/* Assert RESET */
    305	gpiod_set_value_cansleep(nt->reset_gpio, 1);
    306	udelay(20);
    307	/* De-assert RESET */
    308	gpiod_set_value_cansleep(nt->reset_gpio, 0);
    309	usleep_range(11000, 20000);
    310
    311	return 0;
    312}
    313
    314static void nt35560_power_off(struct nt35560 *nt)
    315{
    316	/* Assert RESET */
    317	gpiod_set_value_cansleep(nt->reset_gpio, 1);
    318	usleep_range(11000, 20000);
    319
    320	regulator_disable(nt->supply);
    321}
    322
    323static int nt35560_prepare(struct drm_panel *panel)
    324{
    325	struct nt35560 *nt = panel_to_nt35560(panel);
    326	struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
    327	const u8 mddi = 3;
    328	int ret;
    329
    330	ret = nt35560_power_on(nt);
    331	if (ret)
    332		return ret;
    333
    334	ret = nt35560_read_id(nt);
    335	if (ret) {
    336		dev_err(nt->dev, "failed to read panel ID (%d)\n", ret);
    337		goto err_power_off;
    338	}
    339
    340	/* Enabe tearing mode: send TE (tearing effect) at VBLANK */
    341	ret = mipi_dsi_dcs_set_tear_on(dsi,
    342				       MIPI_DSI_DCS_TEAR_MODE_VBLANK);
    343	if (ret) {
    344		dev_err(nt->dev, "failed to enable vblank TE (%d)\n", ret);
    345		goto err_power_off;
    346	}
    347
    348	/*
    349	 * Set MDDI
    350	 *
    351	 * This presumably deactivates the Qualcomm MDDI interface and
    352	 * selects DSI, similar code is found in other drivers such as the
    353	 * Sharp LS043T1LE01 which makes us suspect that this panel may be
    354	 * using a Novatek NT35565 or similar display driver chip that shares
    355	 * this command. Due to the lack of documentation we cannot know for
    356	 * sure.
    357	 */
    358	ret = mipi_dsi_dcs_write(dsi, NT35560_DCS_SET_MDDI,
    359				 &mddi, sizeof(mddi));
    360	if (ret < 0) {
    361		dev_err(nt->dev, "failed to set MDDI (%d)\n", ret);
    362		goto err_power_off;
    363	}
    364
    365	/* Exit sleep mode */
    366	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
    367	if (ret) {
    368		dev_err(nt->dev, "failed to exit sleep mode (%d)\n", ret);
    369		goto err_power_off;
    370	}
    371	msleep(140);
    372
    373	ret = mipi_dsi_dcs_set_display_on(dsi);
    374	if (ret) {
    375		dev_err(nt->dev, "failed to turn display on (%d)\n", ret);
    376		goto err_power_off;
    377	}
    378	if (nt->video_mode) {
    379		/* In video mode turn peripheral on */
    380		ret = mipi_dsi_turn_on_peripheral(dsi);
    381		if (ret) {
    382			dev_err(nt->dev, "failed to turn on peripheral\n");
    383			goto err_power_off;
    384		}
    385	}
    386
    387	return 0;
    388
    389err_power_off:
    390	nt35560_power_off(nt);
    391	return ret;
    392}
    393
    394static int nt35560_unprepare(struct drm_panel *panel)
    395{
    396	struct nt35560 *nt = panel_to_nt35560(panel);
    397	struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
    398	int ret;
    399
    400	ret = mipi_dsi_dcs_set_display_off(dsi);
    401	if (ret) {
    402		dev_err(nt->dev, "failed to turn display off (%d)\n", ret);
    403		return ret;
    404	}
    405
    406	/* Enter sleep mode */
    407	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
    408	if (ret) {
    409		dev_err(nt->dev, "failed to enter sleep mode (%d)\n", ret);
    410		return ret;
    411	}
    412	msleep(85);
    413
    414	nt35560_power_off(nt);
    415
    416	return 0;
    417}
    418
    419
    420static int nt35560_get_modes(struct drm_panel *panel,
    421			     struct drm_connector *connector)
    422{
    423	struct nt35560 *nt = panel_to_nt35560(panel);
    424	const struct nt35560_config *conf = nt->conf;
    425	struct drm_display_mode *mode;
    426
    427	if (nt->video_mode)
    428		mode = drm_mode_duplicate(connector->dev,
    429					  conf->vid_mode);
    430	else
    431		mode = drm_mode_duplicate(connector->dev,
    432					  conf->cmd_mode);
    433	if (!mode) {
    434		dev_err(panel->dev, "bad mode or failed to add mode\n");
    435		return -EINVAL;
    436	}
    437	drm_mode_set_name(mode);
    438	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
    439
    440	connector->display_info.width_mm = mode->width_mm;
    441	connector->display_info.height_mm = mode->height_mm;
    442
    443	drm_mode_probed_add(connector, mode);
    444
    445	return 1; /* Number of modes */
    446}
    447
    448static const struct drm_panel_funcs nt35560_drm_funcs = {
    449	.unprepare = nt35560_unprepare,
    450	.prepare = nt35560_prepare,
    451	.get_modes = nt35560_get_modes,
    452};
    453
    454static int nt35560_probe(struct mipi_dsi_device *dsi)
    455{
    456	struct device *dev = &dsi->dev;
    457	struct nt35560 *nt;
    458	int ret;
    459
    460	nt = devm_kzalloc(dev, sizeof(struct nt35560), GFP_KERNEL);
    461	if (!nt)
    462		return -ENOMEM;
    463	nt->video_mode = of_property_read_bool(dev->of_node,
    464						"enforce-video-mode");
    465
    466	mipi_dsi_set_drvdata(dsi, nt);
    467	nt->dev = dev;
    468
    469	nt->conf = of_device_get_match_data(dev);
    470	if (!nt->conf) {
    471		dev_err(dev, "missing device configuration\n");
    472		return -ENODEV;
    473	}
    474
    475	dsi->lanes = 2;
    476	dsi->format = MIPI_DSI_FMT_RGB888;
    477	/*
    478	 * FIXME: these come from the ST-Ericsson vendor driver for the
    479	 * HREF520 and seems to reflect limitations in the PLLs on that
    480	 * platform, if you have the datasheet, please cross-check the
    481	 * actual max rates.
    482	 */
    483	dsi->lp_rate = 19200000;
    484	dsi->hs_rate = 420160000;
    485
    486	if (nt->video_mode)
    487		/* Burst mode using event for sync */
    488		dsi->mode_flags =
    489			MIPI_DSI_MODE_VIDEO |
    490			MIPI_DSI_MODE_VIDEO_BURST;
    491	else
    492		dsi->mode_flags =
    493			MIPI_DSI_CLOCK_NON_CONTINUOUS;
    494
    495	nt->supply = devm_regulator_get(dev, "vddi");
    496	if (IS_ERR(nt->supply))
    497		return PTR_ERR(nt->supply);
    498
    499	/* This asserts RESET by default */
    500	nt->reset_gpio = devm_gpiod_get_optional(dev, "reset",
    501						 GPIOD_OUT_HIGH);
    502	if (IS_ERR(nt->reset_gpio))
    503		return dev_err_probe(dev, PTR_ERR(nt->reset_gpio),
    504				     "failed to request GPIO\n");
    505
    506	drm_panel_init(&nt->panel, dev, &nt35560_drm_funcs,
    507		       DRM_MODE_CONNECTOR_DSI);
    508
    509	nt->panel.backlight = devm_backlight_device_register(dev, "nt35560", dev, nt,
    510					&nt35560_bl_ops, &nt35560_bl_props);
    511	if (IS_ERR(nt->panel.backlight))
    512		return dev_err_probe(dev, PTR_ERR(nt->panel.backlight),
    513				     "failed to register backlight device\n");
    514
    515	drm_panel_add(&nt->panel);
    516
    517	ret = mipi_dsi_attach(dsi);
    518	if (ret < 0) {
    519		drm_panel_remove(&nt->panel);
    520		return ret;
    521	}
    522
    523	return 0;
    524}
    525
    526static int nt35560_remove(struct mipi_dsi_device *dsi)
    527{
    528	struct nt35560 *nt = mipi_dsi_get_drvdata(dsi);
    529
    530	mipi_dsi_detach(dsi);
    531	drm_panel_remove(&nt->panel);
    532
    533	return 0;
    534}
    535
    536static const struct of_device_id nt35560_of_match[] = {
    537	{
    538		.compatible = "sony,acx424akp",
    539		.data = &sony_acx424akp_data,
    540	},
    541	{
    542		.compatible = "sony,acx424akm",
    543		.data = &sony_acx424akm_data,
    544	},
    545	{ /* sentinel */ }
    546};
    547MODULE_DEVICE_TABLE(of, nt35560_of_match);
    548
    549static struct mipi_dsi_driver nt35560_driver = {
    550	.probe = nt35560_probe,
    551	.remove = nt35560_remove,
    552	.driver = {
    553		.name = "panel-novatek-nt35560",
    554		.of_match_table = nt35560_of_match,
    555	},
    556};
    557module_mipi_dsi_driver(nt35560_driver);
    558
    559MODULE_AUTHOR("Linus Wallei <linus.walleij@linaro.org>");
    560MODULE_DESCRIPTION("MIPI-DSI Novatek NT35560 Panel Driver");
    561MODULE_LICENSE("GPL v2");