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-seiko-43wvf1g.c (7675B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2017 NXP Semiconductors.
      4 * Author: Marco Franchi <marco.franchi@nxp.com>
      5 *
      6 * Based on Panel Simple driver by Thierry Reding <treding@nvidia.com>
      7 */
      8
      9#include <linux/delay.h>
     10#include <linux/module.h>
     11#include <linux/of.h>
     12#include <linux/platform_device.h>
     13#include <linux/regulator/consumer.h>
     14
     15#include <video/display_timing.h>
     16#include <video/videomode.h>
     17
     18#include <drm/drm_crtc.h>
     19#include <drm/drm_device.h>
     20#include <drm/drm_panel.h>
     21
     22struct seiko_panel_desc {
     23	const struct drm_display_mode *modes;
     24	unsigned int num_modes;
     25	const struct display_timing *timings;
     26	unsigned int num_timings;
     27
     28	unsigned int bpc;
     29
     30	/**
     31	 * @width: width (in millimeters) of the panel's active display area
     32	 * @height: height (in millimeters) of the panel's active display area
     33	 */
     34	struct {
     35		unsigned int width;
     36		unsigned int height;
     37	} size;
     38
     39	u32 bus_format;
     40	u32 bus_flags;
     41};
     42
     43struct seiko_panel {
     44	struct drm_panel base;
     45	bool prepared;
     46	bool enabled;
     47	const struct seiko_panel_desc *desc;
     48	struct regulator *dvdd;
     49	struct regulator *avdd;
     50};
     51
     52static inline struct seiko_panel *to_seiko_panel(struct drm_panel *panel)
     53{
     54	return container_of(panel, struct seiko_panel, base);
     55}
     56
     57static int seiko_panel_get_fixed_modes(struct seiko_panel *panel,
     58				       struct drm_connector *connector)
     59{
     60	struct drm_display_mode *mode;
     61	unsigned int i, num = 0;
     62
     63	if (!panel->desc)
     64		return 0;
     65
     66	for (i = 0; i < panel->desc->num_timings; i++) {
     67		const struct display_timing *dt = &panel->desc->timings[i];
     68		struct videomode vm;
     69
     70		videomode_from_timing(dt, &vm);
     71		mode = drm_mode_create(connector->dev);
     72		if (!mode) {
     73			dev_err(panel->base.dev, "failed to add mode %ux%u\n",
     74				dt->hactive.typ, dt->vactive.typ);
     75			continue;
     76		}
     77
     78		drm_display_mode_from_videomode(&vm, mode);
     79
     80		mode->type |= DRM_MODE_TYPE_DRIVER;
     81
     82		if (panel->desc->num_timings == 1)
     83			mode->type |= DRM_MODE_TYPE_PREFERRED;
     84
     85		drm_mode_probed_add(connector, mode);
     86		num++;
     87	}
     88
     89	for (i = 0; i < panel->desc->num_modes; i++) {
     90		const struct drm_display_mode *m = &panel->desc->modes[i];
     91
     92		mode = drm_mode_duplicate(connector->dev, m);
     93		if (!mode) {
     94			dev_err(panel->base.dev, "failed to add mode %ux%u@%u\n",
     95				m->hdisplay, m->vdisplay,
     96				drm_mode_vrefresh(m));
     97			continue;
     98		}
     99
    100		mode->type |= DRM_MODE_TYPE_DRIVER;
    101
    102		if (panel->desc->num_modes == 1)
    103			mode->type |= DRM_MODE_TYPE_PREFERRED;
    104
    105		drm_mode_set_name(mode);
    106
    107		drm_mode_probed_add(connector, mode);
    108		num++;
    109	}
    110
    111	connector->display_info.bpc = panel->desc->bpc;
    112	connector->display_info.width_mm = panel->desc->size.width;
    113	connector->display_info.height_mm = panel->desc->size.height;
    114	if (panel->desc->bus_format)
    115		drm_display_info_set_bus_formats(&connector->display_info,
    116						 &panel->desc->bus_format, 1);
    117	connector->display_info.bus_flags = panel->desc->bus_flags;
    118
    119	return num;
    120}
    121
    122static int seiko_panel_disable(struct drm_panel *panel)
    123{
    124	struct seiko_panel *p = to_seiko_panel(panel);
    125
    126	if (!p->enabled)
    127		return 0;
    128
    129	p->enabled = false;
    130
    131	return 0;
    132}
    133
    134static int seiko_panel_unprepare(struct drm_panel *panel)
    135{
    136	struct seiko_panel *p = to_seiko_panel(panel);
    137
    138	if (!p->prepared)
    139		return 0;
    140
    141	regulator_disable(p->avdd);
    142
    143	/* Add a 100ms delay as per the panel datasheet */
    144	msleep(100);
    145
    146	regulator_disable(p->dvdd);
    147
    148	p->prepared = false;
    149
    150	return 0;
    151}
    152
    153static int seiko_panel_prepare(struct drm_panel *panel)
    154{
    155	struct seiko_panel *p = to_seiko_panel(panel);
    156	int err;
    157
    158	if (p->prepared)
    159		return 0;
    160
    161	err = regulator_enable(p->dvdd);
    162	if (err < 0) {
    163		dev_err(panel->dev, "failed to enable dvdd: %d\n", err);
    164		return err;
    165	}
    166
    167	/* Add a 100ms delay as per the panel datasheet */
    168	msleep(100);
    169
    170	err = regulator_enable(p->avdd);
    171	if (err < 0) {
    172		dev_err(panel->dev, "failed to enable avdd: %d\n", err);
    173		goto disable_dvdd;
    174	}
    175
    176	p->prepared = true;
    177
    178	return 0;
    179
    180disable_dvdd:
    181	regulator_disable(p->dvdd);
    182	return err;
    183}
    184
    185static int seiko_panel_enable(struct drm_panel *panel)
    186{
    187	struct seiko_panel *p = to_seiko_panel(panel);
    188
    189	if (p->enabled)
    190		return 0;
    191
    192	p->enabled = true;
    193
    194	return 0;
    195}
    196
    197static int seiko_panel_get_modes(struct drm_panel *panel,
    198				 struct drm_connector *connector)
    199{
    200	struct seiko_panel *p = to_seiko_panel(panel);
    201
    202	/* add hard-coded panel modes */
    203	return seiko_panel_get_fixed_modes(p, connector);
    204}
    205
    206static int seiko_panel_get_timings(struct drm_panel *panel,
    207				    unsigned int num_timings,
    208				    struct display_timing *timings)
    209{
    210	struct seiko_panel *p = to_seiko_panel(panel);
    211	unsigned int i;
    212
    213	if (p->desc->num_timings < num_timings)
    214		num_timings = p->desc->num_timings;
    215
    216	if (timings)
    217		for (i = 0; i < num_timings; i++)
    218			timings[i] = p->desc->timings[i];
    219
    220	return p->desc->num_timings;
    221}
    222
    223static const struct drm_panel_funcs seiko_panel_funcs = {
    224	.disable = seiko_panel_disable,
    225	.unprepare = seiko_panel_unprepare,
    226	.prepare = seiko_panel_prepare,
    227	.enable = seiko_panel_enable,
    228	.get_modes = seiko_panel_get_modes,
    229	.get_timings = seiko_panel_get_timings,
    230};
    231
    232static int seiko_panel_probe(struct device *dev,
    233					const struct seiko_panel_desc *desc)
    234{
    235	struct seiko_panel *panel;
    236	int err;
    237
    238	panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL);
    239	if (!panel)
    240		return -ENOMEM;
    241
    242	panel->enabled = false;
    243	panel->prepared = false;
    244	panel->desc = desc;
    245
    246	panel->dvdd = devm_regulator_get(dev, "dvdd");
    247	if (IS_ERR(panel->dvdd))
    248		return PTR_ERR(panel->dvdd);
    249
    250	panel->avdd = devm_regulator_get(dev, "avdd");
    251	if (IS_ERR(panel->avdd))
    252		return PTR_ERR(panel->avdd);
    253
    254	drm_panel_init(&panel->base, dev, &seiko_panel_funcs,
    255		       DRM_MODE_CONNECTOR_DPI);
    256
    257	err = drm_panel_of_backlight(&panel->base);
    258	if (err)
    259		return err;
    260
    261	drm_panel_add(&panel->base);
    262
    263	dev_set_drvdata(dev, panel);
    264
    265	return 0;
    266}
    267
    268static int seiko_panel_remove(struct platform_device *pdev)
    269{
    270	struct seiko_panel *panel = platform_get_drvdata(pdev);
    271
    272	drm_panel_remove(&panel->base);
    273	drm_panel_disable(&panel->base);
    274
    275	return 0;
    276}
    277
    278static void seiko_panel_shutdown(struct platform_device *pdev)
    279{
    280	struct seiko_panel *panel = platform_get_drvdata(pdev);
    281
    282	drm_panel_disable(&panel->base);
    283}
    284
    285static const struct display_timing seiko_43wvf1g_timing = {
    286	.pixelclock = { 33500000, 33500000, 33500000 },
    287	.hactive = { 800, 800, 800 },
    288	.hfront_porch = {  164, 164, 164 },
    289	.hback_porch = { 89, 89, 89 },
    290	.hsync_len = { 10, 10, 10 },
    291	.vactive = { 480, 480, 480 },
    292	.vfront_porch = { 10, 10, 10 },
    293	.vback_porch = { 23, 23, 23 },
    294	.vsync_len = { 10, 10, 10 },
    295	.flags = DISPLAY_FLAGS_DE_LOW,
    296};
    297
    298static const struct seiko_panel_desc seiko_43wvf1g = {
    299	.timings = &seiko_43wvf1g_timing,
    300	.num_timings = 1,
    301	.bpc = 8,
    302	.size = {
    303		.width = 93,
    304		.height = 57,
    305	},
    306	.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
    307	.bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE,
    308};
    309
    310static const struct of_device_id platform_of_match[] = {
    311	{
    312		.compatible = "sii,43wvf1g",
    313		.data = &seiko_43wvf1g,
    314	}, {
    315		/* sentinel */
    316	}
    317};
    318MODULE_DEVICE_TABLE(of, platform_of_match);
    319
    320static int seiko_panel_platform_probe(struct platform_device *pdev)
    321{
    322	const struct of_device_id *id;
    323
    324	id = of_match_node(platform_of_match, pdev->dev.of_node);
    325	if (!id)
    326		return -ENODEV;
    327
    328	return seiko_panel_probe(&pdev->dev, id->data);
    329}
    330
    331static struct platform_driver seiko_panel_platform_driver = {
    332	.driver = {
    333		.name = "seiko_panel",
    334		.of_match_table = platform_of_match,
    335	},
    336	.probe = seiko_panel_platform_probe,
    337	.remove = seiko_panel_remove,
    338	.shutdown = seiko_panel_shutdown,
    339};
    340module_platform_driver(seiko_panel_platform_driver);
    341
    342MODULE_AUTHOR("Marco Franchi <marco.franchi@nxp.com>");
    343MODULE_DESCRIPTION("Seiko 43WVF1G panel driver");
    344MODULE_LICENSE("GPL v2");