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-tpo-td043mtea1.c (14714B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * TPO TD043MTEA1 Panel driver
      4 *
      5 * Author: Gražvydas Ignotas <notasas@gmail.com>
      6 * Converted to new DSS device model: Tomi Valkeinen <tomi.valkeinen@ti.com>
      7 */
      8
      9#include <linux/module.h>
     10#include <linux/delay.h>
     11#include <linux/spi/spi.h>
     12#include <linux/regulator/consumer.h>
     13#include <linux/gpio.h>
     14#include <linux/err.h>
     15#include <linux/slab.h>
     16#include <linux/of_gpio.h>
     17
     18#include <video/omapfb_dss.h>
     19
     20#define TPO_R02_MODE(x)		((x) & 7)
     21#define TPO_R02_MODE_800x480	7
     22#define TPO_R02_NCLK_RISING	BIT(3)
     23#define TPO_R02_HSYNC_HIGH	BIT(4)
     24#define TPO_R02_VSYNC_HIGH	BIT(5)
     25
     26#define TPO_R03_NSTANDBY	BIT(0)
     27#define TPO_R03_EN_CP_CLK	BIT(1)
     28#define TPO_R03_EN_VGL_PUMP	BIT(2)
     29#define TPO_R03_EN_PWM		BIT(3)
     30#define TPO_R03_DRIVING_CAP_100	BIT(4)
     31#define TPO_R03_EN_PRE_CHARGE	BIT(6)
     32#define TPO_R03_SOFTWARE_CTL	BIT(7)
     33
     34#define TPO_R04_NFLIP_H		BIT(0)
     35#define TPO_R04_NFLIP_V		BIT(1)
     36#define TPO_R04_CP_CLK_FREQ_1H	BIT(2)
     37#define TPO_R04_VGL_FREQ_1H	BIT(4)
     38
     39#define TPO_R03_VAL_NORMAL (TPO_R03_NSTANDBY | TPO_R03_EN_CP_CLK | \
     40			TPO_R03_EN_VGL_PUMP |  TPO_R03_EN_PWM | \
     41			TPO_R03_DRIVING_CAP_100 | TPO_R03_EN_PRE_CHARGE | \
     42			TPO_R03_SOFTWARE_CTL)
     43
     44#define TPO_R03_VAL_STANDBY (TPO_R03_DRIVING_CAP_100 | \
     45			TPO_R03_EN_PRE_CHARGE | TPO_R03_SOFTWARE_CTL)
     46
     47static const u16 tpo_td043_def_gamma[12] = {
     48	105, 315, 381, 431, 490, 537, 579, 686, 780, 837, 880, 1023
     49};
     50
     51struct panel_drv_data {
     52	struct omap_dss_device	dssdev;
     53	struct omap_dss_device *in;
     54
     55	struct omap_video_timings videomode;
     56
     57	int data_lines;
     58
     59	struct spi_device *spi;
     60	struct regulator *vcc_reg;
     61	int nreset_gpio;
     62	u16 gamma[12];
     63	u32 mode;
     64	u32 hmirror:1;
     65	u32 vmirror:1;
     66	u32 powered_on:1;
     67	u32 spi_suspended:1;
     68	u32 power_on_resume:1;
     69};
     70
     71static const struct omap_video_timings tpo_td043_timings = {
     72	.x_res		= 800,
     73	.y_res		= 480,
     74
     75	.pixelclock	= 36000000,
     76
     77	.hsw		= 1,
     78	.hfp		= 68,
     79	.hbp		= 214,
     80
     81	.vsw		= 1,
     82	.vfp		= 39,
     83	.vbp		= 34,
     84
     85	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
     86	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
     87	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_FALLING_EDGE,
     88	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
     89	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
     90};
     91
     92#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
     93
     94static int tpo_td043_write(struct spi_device *spi, u8 addr, u8 data)
     95{
     96	struct spi_message	m;
     97	struct spi_transfer	xfer;
     98	u16			w;
     99	int			r;
    100
    101	spi_message_init(&m);
    102
    103	memset(&xfer, 0, sizeof(xfer));
    104
    105	w = ((u16)addr << 10) | (1 << 8) | data;
    106	xfer.tx_buf = &w;
    107	xfer.bits_per_word = 16;
    108	xfer.len = 2;
    109	spi_message_add_tail(&xfer, &m);
    110
    111	r = spi_sync(spi, &m);
    112	if (r < 0)
    113		dev_warn(&spi->dev, "failed to write to LCD reg (%d)\n", r);
    114	return r;
    115}
    116
    117static void tpo_td043_write_gamma(struct spi_device *spi, u16 gamma[12])
    118{
    119	u8 i, val;
    120
    121	/* gamma bits [9:8] */
    122	for (val = i = 0; i < 4; i++)
    123		val |= (gamma[i] & 0x300) >> ((i + 1) * 2);
    124	tpo_td043_write(spi, 0x11, val);
    125
    126	for (val = i = 0; i < 4; i++)
    127		val |= (gamma[i+4] & 0x300) >> ((i + 1) * 2);
    128	tpo_td043_write(spi, 0x12, val);
    129
    130	for (val = i = 0; i < 4; i++)
    131		val |= (gamma[i+8] & 0x300) >> ((i + 1) * 2);
    132	tpo_td043_write(spi, 0x13, val);
    133
    134	/* gamma bits [7:0] */
    135	for (val = i = 0; i < 12; i++)
    136		tpo_td043_write(spi, 0x14 + i, gamma[i] & 0xff);
    137}
    138
    139static int tpo_td043_write_mirror(struct spi_device *spi, bool h, bool v)
    140{
    141	u8 reg4 = TPO_R04_NFLIP_H | TPO_R04_NFLIP_V |
    142		TPO_R04_CP_CLK_FREQ_1H | TPO_R04_VGL_FREQ_1H;
    143	if (h)
    144		reg4 &= ~TPO_R04_NFLIP_H;
    145	if (v)
    146		reg4 &= ~TPO_R04_NFLIP_V;
    147
    148	return tpo_td043_write(spi, 4, reg4);
    149}
    150
    151static int tpo_td043_set_hmirror(struct omap_dss_device *dssdev, bool enable)
    152{
    153	struct panel_drv_data *ddata = dev_get_drvdata(dssdev->dev);
    154
    155	ddata->hmirror = enable;
    156	return tpo_td043_write_mirror(ddata->spi, ddata->hmirror,
    157			ddata->vmirror);
    158}
    159
    160static bool tpo_td043_get_hmirror(struct omap_dss_device *dssdev)
    161{
    162	struct panel_drv_data *ddata = dev_get_drvdata(dssdev->dev);
    163
    164	return ddata->hmirror;
    165}
    166
    167static ssize_t tpo_td043_vmirror_show(struct device *dev,
    168	struct device_attribute *attr, char *buf)
    169{
    170	struct panel_drv_data *ddata = dev_get_drvdata(dev);
    171
    172	return sysfs_emit(buf, "%d\n", ddata->vmirror);
    173}
    174
    175static ssize_t tpo_td043_vmirror_store(struct device *dev,
    176	struct device_attribute *attr, const char *buf, size_t count)
    177{
    178	struct panel_drv_data *ddata = dev_get_drvdata(dev);
    179	int val;
    180	int ret;
    181
    182	ret = kstrtoint(buf, 0, &val);
    183	if (ret < 0)
    184		return ret;
    185
    186	val = !!val;
    187
    188	ret = tpo_td043_write_mirror(ddata->spi, ddata->hmirror, val);
    189	if (ret < 0)
    190		return ret;
    191
    192	ddata->vmirror = val;
    193
    194	return count;
    195}
    196
    197static ssize_t tpo_td043_mode_show(struct device *dev,
    198	struct device_attribute *attr, char *buf)
    199{
    200	struct panel_drv_data *ddata = dev_get_drvdata(dev);
    201
    202	return sysfs_emit(buf, "%d\n", ddata->mode);
    203}
    204
    205static ssize_t tpo_td043_mode_store(struct device *dev,
    206	struct device_attribute *attr, const char *buf, size_t count)
    207{
    208	struct panel_drv_data *ddata = dev_get_drvdata(dev);
    209	long val;
    210	int ret;
    211
    212	ret = kstrtol(buf, 0, &val);
    213	if (ret != 0 || val & ~7)
    214		return -EINVAL;
    215
    216	ddata->mode = val;
    217
    218	val |= TPO_R02_NCLK_RISING;
    219	tpo_td043_write(ddata->spi, 2, val);
    220
    221	return count;
    222}
    223
    224static ssize_t tpo_td043_gamma_show(struct device *dev,
    225	struct device_attribute *attr, char *buf)
    226{
    227	struct panel_drv_data *ddata = dev_get_drvdata(dev);
    228	ssize_t len = 0;
    229	int ret;
    230	int i;
    231
    232	for (i = 0; i < ARRAY_SIZE(ddata->gamma); i++) {
    233		ret = snprintf(buf + len, PAGE_SIZE - len, "%u ",
    234				ddata->gamma[i]);
    235		if (ret < 0)
    236			return ret;
    237		len += ret;
    238	}
    239	buf[len - 1] = '\n';
    240
    241	return len;
    242}
    243
    244static ssize_t tpo_td043_gamma_store(struct device *dev,
    245	struct device_attribute *attr, const char *buf, size_t count)
    246{
    247	struct panel_drv_data *ddata = dev_get_drvdata(dev);
    248	unsigned int g[12];
    249	int ret;
    250	int i;
    251
    252	ret = sscanf(buf, "%u %u %u %u %u %u %u %u %u %u %u %u",
    253			&g[0], &g[1], &g[2], &g[3], &g[4], &g[5],
    254			&g[6], &g[7], &g[8], &g[9], &g[10], &g[11]);
    255
    256	if (ret != 12)
    257		return -EINVAL;
    258
    259	for (i = 0; i < 12; i++)
    260		ddata->gamma[i] = g[i];
    261
    262	tpo_td043_write_gamma(ddata->spi, ddata->gamma);
    263
    264	return count;
    265}
    266
    267static DEVICE_ATTR(vmirror, S_IRUGO | S_IWUSR,
    268		tpo_td043_vmirror_show, tpo_td043_vmirror_store);
    269static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
    270		tpo_td043_mode_show, tpo_td043_mode_store);
    271static DEVICE_ATTR(gamma, S_IRUGO | S_IWUSR,
    272		tpo_td043_gamma_show, tpo_td043_gamma_store);
    273
    274static struct attribute *tpo_td043_attrs[] = {
    275	&dev_attr_vmirror.attr,
    276	&dev_attr_mode.attr,
    277	&dev_attr_gamma.attr,
    278	NULL,
    279};
    280
    281static const struct attribute_group tpo_td043_attr_group = {
    282	.attrs = tpo_td043_attrs,
    283};
    284
    285static int tpo_td043_power_on(struct panel_drv_data *ddata)
    286{
    287	int r;
    288
    289	if (ddata->powered_on)
    290		return 0;
    291
    292	r = regulator_enable(ddata->vcc_reg);
    293	if (r != 0)
    294		return r;
    295
    296	/* wait for panel to stabilize */
    297	msleep(160);
    298
    299	if (gpio_is_valid(ddata->nreset_gpio))
    300		gpio_set_value(ddata->nreset_gpio, 1);
    301
    302	tpo_td043_write(ddata->spi, 2,
    303			TPO_R02_MODE(ddata->mode) | TPO_R02_NCLK_RISING);
    304	tpo_td043_write(ddata->spi, 3, TPO_R03_VAL_NORMAL);
    305	tpo_td043_write(ddata->spi, 0x20, 0xf0);
    306	tpo_td043_write(ddata->spi, 0x21, 0xf0);
    307	tpo_td043_write_mirror(ddata->spi, ddata->hmirror,
    308			ddata->vmirror);
    309	tpo_td043_write_gamma(ddata->spi, ddata->gamma);
    310
    311	ddata->powered_on = 1;
    312	return 0;
    313}
    314
    315static void tpo_td043_power_off(struct panel_drv_data *ddata)
    316{
    317	if (!ddata->powered_on)
    318		return;
    319
    320	tpo_td043_write(ddata->spi, 3,
    321			TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM);
    322
    323	if (gpio_is_valid(ddata->nreset_gpio))
    324		gpio_set_value(ddata->nreset_gpio, 0);
    325
    326	/* wait for at least 2 vsyncs before cutting off power */
    327	msleep(50);
    328
    329	tpo_td043_write(ddata->spi, 3, TPO_R03_VAL_STANDBY);
    330
    331	regulator_disable(ddata->vcc_reg);
    332
    333	ddata->powered_on = 0;
    334}
    335
    336static int tpo_td043_connect(struct omap_dss_device *dssdev)
    337{
    338	struct panel_drv_data *ddata = to_panel_data(dssdev);
    339	struct omap_dss_device *in = ddata->in;
    340
    341	if (omapdss_device_is_connected(dssdev))
    342		return 0;
    343
    344	return in->ops.dpi->connect(in, dssdev);
    345}
    346
    347static void tpo_td043_disconnect(struct omap_dss_device *dssdev)
    348{
    349	struct panel_drv_data *ddata = to_panel_data(dssdev);
    350	struct omap_dss_device *in = ddata->in;
    351
    352	if (!omapdss_device_is_connected(dssdev))
    353		return;
    354
    355	in->ops.dpi->disconnect(in, dssdev);
    356}
    357
    358static int tpo_td043_enable(struct omap_dss_device *dssdev)
    359{
    360	struct panel_drv_data *ddata = to_panel_data(dssdev);
    361	struct omap_dss_device *in = ddata->in;
    362	int r;
    363
    364	if (!omapdss_device_is_connected(dssdev))
    365		return -ENODEV;
    366
    367	if (omapdss_device_is_enabled(dssdev))
    368		return 0;
    369
    370	if (ddata->data_lines)
    371		in->ops.dpi->set_data_lines(in, ddata->data_lines);
    372	in->ops.dpi->set_timings(in, &ddata->videomode);
    373
    374	r = in->ops.dpi->enable(in);
    375	if (r)
    376		return r;
    377
    378	/*
    379	 * If we are resuming from system suspend, SPI clocks might not be
    380	 * enabled yet, so we'll program the LCD from SPI PM resume callback.
    381	 */
    382	if (!ddata->spi_suspended) {
    383		r = tpo_td043_power_on(ddata);
    384		if (r) {
    385			in->ops.dpi->disable(in);
    386			return r;
    387		}
    388	}
    389
    390	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
    391
    392	return 0;
    393}
    394
    395static void tpo_td043_disable(struct omap_dss_device *dssdev)
    396{
    397	struct panel_drv_data *ddata = to_panel_data(dssdev);
    398	struct omap_dss_device *in = ddata->in;
    399
    400	if (!omapdss_device_is_enabled(dssdev))
    401		return;
    402
    403	in->ops.dpi->disable(in);
    404
    405	if (!ddata->spi_suspended)
    406		tpo_td043_power_off(ddata);
    407
    408	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
    409}
    410
    411static void tpo_td043_set_timings(struct omap_dss_device *dssdev,
    412		struct omap_video_timings *timings)
    413{
    414	struct panel_drv_data *ddata = to_panel_data(dssdev);
    415	struct omap_dss_device *in = ddata->in;
    416
    417	ddata->videomode = *timings;
    418	dssdev->panel.timings = *timings;
    419
    420	in->ops.dpi->set_timings(in, timings);
    421}
    422
    423static void tpo_td043_get_timings(struct omap_dss_device *dssdev,
    424		struct omap_video_timings *timings)
    425{
    426	struct panel_drv_data *ddata = to_panel_data(dssdev);
    427
    428	*timings = ddata->videomode;
    429}
    430
    431static int tpo_td043_check_timings(struct omap_dss_device *dssdev,
    432		struct omap_video_timings *timings)
    433{
    434	struct panel_drv_data *ddata = to_panel_data(dssdev);
    435	struct omap_dss_device *in = ddata->in;
    436
    437	return in->ops.dpi->check_timings(in, timings);
    438}
    439
    440static struct omap_dss_driver tpo_td043_ops = {
    441	.connect	= tpo_td043_connect,
    442	.disconnect	= tpo_td043_disconnect,
    443
    444	.enable		= tpo_td043_enable,
    445	.disable	= tpo_td043_disable,
    446
    447	.set_timings	= tpo_td043_set_timings,
    448	.get_timings	= tpo_td043_get_timings,
    449	.check_timings	= tpo_td043_check_timings,
    450
    451	.set_mirror	= tpo_td043_set_hmirror,
    452	.get_mirror	= tpo_td043_get_hmirror,
    453
    454	.get_resolution	= omapdss_default_get_resolution,
    455};
    456
    457
    458static int tpo_td043_probe_of(struct spi_device *spi)
    459{
    460	struct device_node *node = spi->dev.of_node;
    461	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
    462	struct omap_dss_device *in;
    463	int gpio;
    464
    465	gpio = of_get_named_gpio(node, "reset-gpios", 0);
    466	if (!gpio_is_valid(gpio)) {
    467		dev_err(&spi->dev, "failed to parse enable gpio\n");
    468		return gpio;
    469	}
    470	ddata->nreset_gpio = gpio;
    471
    472	in = omapdss_of_find_source_for_first_ep(node);
    473	if (IS_ERR(in)) {
    474		dev_err(&spi->dev, "failed to find video source\n");
    475		return PTR_ERR(in);
    476	}
    477
    478	ddata->in = in;
    479
    480	return 0;
    481}
    482
    483static int tpo_td043_probe(struct spi_device *spi)
    484{
    485	struct panel_drv_data *ddata;
    486	struct omap_dss_device *dssdev;
    487	int r;
    488
    489	dev_dbg(&spi->dev, "%s\n", __func__);
    490
    491	if (!spi->dev.of_node)
    492		return -ENODEV;
    493
    494	spi->bits_per_word = 16;
    495	spi->mode = SPI_MODE_0;
    496
    497	r = spi_setup(spi);
    498	if (r < 0) {
    499		dev_err(&spi->dev, "spi_setup failed: %d\n", r);
    500		return r;
    501	}
    502
    503	ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
    504	if (ddata == NULL)
    505		return -ENOMEM;
    506
    507	dev_set_drvdata(&spi->dev, ddata);
    508
    509	ddata->spi = spi;
    510
    511	r = tpo_td043_probe_of(spi);
    512	if (r)
    513		return r;
    514
    515	ddata->mode = TPO_R02_MODE_800x480;
    516	memcpy(ddata->gamma, tpo_td043_def_gamma, sizeof(ddata->gamma));
    517
    518	ddata->vcc_reg = devm_regulator_get(&spi->dev, "vcc");
    519	if (IS_ERR(ddata->vcc_reg)) {
    520		r = dev_err_probe(&spi->dev, r, "failed to get LCD VCC regulator\n");
    521		goto err_regulator;
    522	}
    523
    524	if (gpio_is_valid(ddata->nreset_gpio)) {
    525		r = devm_gpio_request_one(&spi->dev,
    526				ddata->nreset_gpio, GPIOF_OUT_INIT_LOW,
    527				"lcd reset");
    528		if (r < 0) {
    529			dev_err(&spi->dev, "couldn't request reset GPIO\n");
    530			goto err_gpio_req;
    531		}
    532	}
    533
    534	r = sysfs_create_group(&spi->dev.kobj, &tpo_td043_attr_group);
    535	if (r) {
    536		dev_err(&spi->dev, "failed to create sysfs files\n");
    537		goto err_sysfs;
    538	}
    539
    540	ddata->videomode = tpo_td043_timings;
    541
    542	dssdev = &ddata->dssdev;
    543	dssdev->dev = &spi->dev;
    544	dssdev->driver = &tpo_td043_ops;
    545	dssdev->type = OMAP_DISPLAY_TYPE_DPI;
    546	dssdev->owner = THIS_MODULE;
    547	dssdev->panel.timings = ddata->videomode;
    548
    549	r = omapdss_register_display(dssdev);
    550	if (r) {
    551		dev_err(&spi->dev, "Failed to register panel\n");
    552		goto err_reg;
    553	}
    554
    555	return 0;
    556
    557err_reg:
    558	sysfs_remove_group(&spi->dev.kobj, &tpo_td043_attr_group);
    559err_sysfs:
    560err_gpio_req:
    561err_regulator:
    562	omap_dss_put_device(ddata->in);
    563	return r;
    564}
    565
    566static void tpo_td043_remove(struct spi_device *spi)
    567{
    568	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
    569	struct omap_dss_device *dssdev = &ddata->dssdev;
    570	struct omap_dss_device *in = ddata->in;
    571
    572	dev_dbg(&ddata->spi->dev, "%s\n", __func__);
    573
    574	omapdss_unregister_display(dssdev);
    575
    576	tpo_td043_disable(dssdev);
    577	tpo_td043_disconnect(dssdev);
    578
    579	omap_dss_put_device(in);
    580
    581	sysfs_remove_group(&spi->dev.kobj, &tpo_td043_attr_group);
    582}
    583
    584#ifdef CONFIG_PM_SLEEP
    585static int tpo_td043_spi_suspend(struct device *dev)
    586{
    587	struct panel_drv_data *ddata = dev_get_drvdata(dev);
    588
    589	dev_dbg(dev, "tpo_td043_spi_suspend, tpo %p\n", ddata);
    590
    591	ddata->power_on_resume = ddata->powered_on;
    592	tpo_td043_power_off(ddata);
    593	ddata->spi_suspended = 1;
    594
    595	return 0;
    596}
    597
    598static int tpo_td043_spi_resume(struct device *dev)
    599{
    600	struct panel_drv_data *ddata = dev_get_drvdata(dev);
    601	int ret;
    602
    603	dev_dbg(dev, "tpo_td043_spi_resume\n");
    604
    605	if (ddata->power_on_resume) {
    606		ret = tpo_td043_power_on(ddata);
    607		if (ret)
    608			return ret;
    609	}
    610	ddata->spi_suspended = 0;
    611
    612	return 0;
    613}
    614#endif
    615
    616static SIMPLE_DEV_PM_OPS(tpo_td043_spi_pm,
    617	tpo_td043_spi_suspend, tpo_td043_spi_resume);
    618
    619static const struct of_device_id tpo_td043_of_match[] = {
    620	{ .compatible = "omapdss,tpo,td043mtea1", },
    621	{},
    622};
    623
    624MODULE_DEVICE_TABLE(of, tpo_td043_of_match);
    625
    626static struct spi_driver tpo_td043_spi_driver = {
    627	.driver = {
    628		.name	= "panel-tpo-td043mtea1",
    629		.pm	= &tpo_td043_spi_pm,
    630		.of_match_table = tpo_td043_of_match,
    631		.suppress_bind_attrs = true,
    632	},
    633	.probe	= tpo_td043_probe,
    634	.remove	= tpo_td043_remove,
    635};
    636
    637module_spi_driver(tpo_td043_spi_driver);
    638
    639MODULE_ALIAS("spi:tpo,td043mtea1");
    640MODULE_AUTHOR("Gražvydas Ignotas <notasas@gmail.com>");
    641MODULE_DESCRIPTION("TPO TD043MTEA1 LCD Driver");
    642MODULE_LICENSE("GPL");