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-sharp-ls037v7dw01.c (7613B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * LCD panel driver for Sharp LS037V7DW01
      4 *
      5 * Copyright (C) 2013 Texas Instruments
      6 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
      7 */
      8
      9#include <linux/delay.h>
     10#include <linux/gpio.h>
     11#include <linux/module.h>
     12#include <linux/of.h>
     13#include <linux/of_gpio.h>
     14#include <linux/platform_device.h>
     15#include <linux/slab.h>
     16#include <linux/regulator/consumer.h>
     17#include <video/omapfb_dss.h>
     18
     19struct panel_drv_data {
     20	struct omap_dss_device dssdev;
     21	struct omap_dss_device *in;
     22	struct regulator *vcc;
     23
     24	int data_lines;
     25
     26	struct omap_video_timings videomode;
     27
     28	struct gpio_desc *resb_gpio;	/* low = reset active min 20 us */
     29	struct gpio_desc *ini_gpio;	/* high = power on */
     30	struct gpio_desc *mo_gpio;	/* low = 480x640, high = 240x320 */
     31	struct gpio_desc *lr_gpio;	/* high = conventional horizontal scanning */
     32	struct gpio_desc *ud_gpio;	/* high = conventional vertical scanning */
     33};
     34
     35static const struct omap_video_timings sharp_ls_timings = {
     36	.x_res = 480,
     37	.y_res = 640,
     38
     39	.pixelclock	= 19200000,
     40
     41	.hsw		= 2,
     42	.hfp		= 1,
     43	.hbp		= 28,
     44
     45	.vsw		= 1,
     46	.vfp		= 1,
     47	.vbp		= 1,
     48
     49	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
     50	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
     51	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
     52	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
     53	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_FALLING_EDGE,
     54};
     55
     56#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
     57
     58static int sharp_ls_connect(struct omap_dss_device *dssdev)
     59{
     60	struct panel_drv_data *ddata = to_panel_data(dssdev);
     61	struct omap_dss_device *in = ddata->in;
     62
     63	if (omapdss_device_is_connected(dssdev))
     64		return 0;
     65
     66	return in->ops.dpi->connect(in, dssdev);
     67}
     68
     69static void sharp_ls_disconnect(struct omap_dss_device *dssdev)
     70{
     71	struct panel_drv_data *ddata = to_panel_data(dssdev);
     72	struct omap_dss_device *in = ddata->in;
     73
     74	if (!omapdss_device_is_connected(dssdev))
     75		return;
     76
     77	in->ops.dpi->disconnect(in, dssdev);
     78}
     79
     80static int sharp_ls_enable(struct omap_dss_device *dssdev)
     81{
     82	struct panel_drv_data *ddata = to_panel_data(dssdev);
     83	struct omap_dss_device *in = ddata->in;
     84	int r;
     85
     86	if (!omapdss_device_is_connected(dssdev))
     87		return -ENODEV;
     88
     89	if (omapdss_device_is_enabled(dssdev))
     90		return 0;
     91
     92	if (ddata->data_lines)
     93		in->ops.dpi->set_data_lines(in, ddata->data_lines);
     94	in->ops.dpi->set_timings(in, &ddata->videomode);
     95
     96	if (ddata->vcc) {
     97		r = regulator_enable(ddata->vcc);
     98		if (r != 0)
     99			return r;
    100	}
    101
    102	r = in->ops.dpi->enable(in);
    103	if (r) {
    104		regulator_disable(ddata->vcc);
    105		return r;
    106	}
    107
    108	/* wait couple of vsyncs until enabling the LCD */
    109	msleep(50);
    110
    111	if (ddata->resb_gpio)
    112		gpiod_set_value_cansleep(ddata->resb_gpio, 1);
    113
    114	if (ddata->ini_gpio)
    115		gpiod_set_value_cansleep(ddata->ini_gpio, 1);
    116
    117	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
    118
    119	return 0;
    120}
    121
    122static void sharp_ls_disable(struct omap_dss_device *dssdev)
    123{
    124	struct panel_drv_data *ddata = to_panel_data(dssdev);
    125	struct omap_dss_device *in = ddata->in;
    126
    127	if (!omapdss_device_is_enabled(dssdev))
    128		return;
    129
    130	if (ddata->ini_gpio)
    131		gpiod_set_value_cansleep(ddata->ini_gpio, 0);
    132
    133	if (ddata->resb_gpio)
    134		gpiod_set_value_cansleep(ddata->resb_gpio, 0);
    135
    136	/* wait at least 5 vsyncs after disabling the LCD */
    137
    138	msleep(100);
    139
    140	in->ops.dpi->disable(in);
    141
    142	if (ddata->vcc)
    143		regulator_disable(ddata->vcc);
    144
    145	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
    146}
    147
    148static void sharp_ls_set_timings(struct omap_dss_device *dssdev,
    149		struct omap_video_timings *timings)
    150{
    151	struct panel_drv_data *ddata = to_panel_data(dssdev);
    152	struct omap_dss_device *in = ddata->in;
    153
    154	ddata->videomode = *timings;
    155	dssdev->panel.timings = *timings;
    156
    157	in->ops.dpi->set_timings(in, timings);
    158}
    159
    160static void sharp_ls_get_timings(struct omap_dss_device *dssdev,
    161		struct omap_video_timings *timings)
    162{
    163	struct panel_drv_data *ddata = to_panel_data(dssdev);
    164
    165	*timings = ddata->videomode;
    166}
    167
    168static int sharp_ls_check_timings(struct omap_dss_device *dssdev,
    169		struct omap_video_timings *timings)
    170{
    171	struct panel_drv_data *ddata = to_panel_data(dssdev);
    172	struct omap_dss_device *in = ddata->in;
    173
    174	return in->ops.dpi->check_timings(in, timings);
    175}
    176
    177static struct omap_dss_driver sharp_ls_ops = {
    178	.connect	= sharp_ls_connect,
    179	.disconnect	= sharp_ls_disconnect,
    180
    181	.enable		= sharp_ls_enable,
    182	.disable	= sharp_ls_disable,
    183
    184	.set_timings	= sharp_ls_set_timings,
    185	.get_timings	= sharp_ls_get_timings,
    186	.check_timings	= sharp_ls_check_timings,
    187
    188	.get_resolution	= omapdss_default_get_resolution,
    189};
    190
    191static  int sharp_ls_get_gpio_of(struct device *dev, int index, int val,
    192	const char *desc, struct gpio_desc **gpiod)
    193{
    194	struct gpio_desc *gd;
    195
    196	*gpiod = NULL;
    197
    198	gd = devm_gpiod_get_index(dev, desc, index, GPIOD_OUT_LOW);
    199	if (IS_ERR(gd))
    200		return PTR_ERR(gd);
    201
    202	*gpiod = gd;
    203	return 0;
    204}
    205
    206static int sharp_ls_probe_of(struct platform_device *pdev)
    207{
    208	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
    209	struct device_node *node = pdev->dev.of_node;
    210	struct omap_dss_device *in;
    211	int r;
    212
    213	ddata->vcc = devm_regulator_get(&pdev->dev, "envdd");
    214	if (IS_ERR(ddata->vcc))
    215		return dev_err_probe(&pdev->dev, PTR_ERR(ddata->vcc),
    216				     "failed to get regulator\n");
    217
    218	/* lcd INI */
    219	r = sharp_ls_get_gpio_of(&pdev->dev, 0, 0, "enable", &ddata->ini_gpio);
    220	if (r)
    221		return r;
    222
    223	/* lcd RESB */
    224	r = sharp_ls_get_gpio_of(&pdev->dev, 0, 0, "reset", &ddata->resb_gpio);
    225	if (r)
    226		return r;
    227
    228	/* lcd MO */
    229	r = sharp_ls_get_gpio_of(&pdev->dev, 0, 0, "mode", &ddata->mo_gpio);
    230	if (r)
    231		return r;
    232
    233	/* lcd LR */
    234	r = sharp_ls_get_gpio_of(&pdev->dev, 1, 1, "mode", &ddata->lr_gpio);
    235	if (r)
    236		return r;
    237
    238	/* lcd UD */
    239	r = sharp_ls_get_gpio_of(&pdev->dev, 2, 1, "mode", &ddata->ud_gpio);
    240	if (r)
    241		return r;
    242
    243	in = omapdss_of_find_source_for_first_ep(node);
    244	if (IS_ERR(in)) {
    245		dev_err(&pdev->dev, "failed to find video source\n");
    246		return PTR_ERR(in);
    247	}
    248
    249	ddata->in = in;
    250
    251	return 0;
    252}
    253
    254static int sharp_ls_probe(struct platform_device *pdev)
    255{
    256	struct panel_drv_data *ddata;
    257	struct omap_dss_device *dssdev;
    258	int r;
    259
    260	if (!pdev->dev.of_node)
    261		return -ENODEV;
    262
    263	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
    264	if (ddata == NULL)
    265		return -ENOMEM;
    266
    267	platform_set_drvdata(pdev, ddata);
    268
    269	r = sharp_ls_probe_of(pdev);
    270	if (r)
    271		return r;
    272
    273	ddata->videomode = sharp_ls_timings;
    274
    275	dssdev = &ddata->dssdev;
    276	dssdev->dev = &pdev->dev;
    277	dssdev->driver = &sharp_ls_ops;
    278	dssdev->type = OMAP_DISPLAY_TYPE_DPI;
    279	dssdev->owner = THIS_MODULE;
    280	dssdev->panel.timings = ddata->videomode;
    281	dssdev->phy.dpi.data_lines = ddata->data_lines;
    282
    283	r = omapdss_register_display(dssdev);
    284	if (r) {
    285		dev_err(&pdev->dev, "Failed to register panel\n");
    286		goto err_reg;
    287	}
    288
    289	return 0;
    290
    291err_reg:
    292	omap_dss_put_device(ddata->in);
    293	return r;
    294}
    295
    296static int __exit sharp_ls_remove(struct platform_device *pdev)
    297{
    298	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
    299	struct omap_dss_device *dssdev = &ddata->dssdev;
    300	struct omap_dss_device *in = ddata->in;
    301
    302	omapdss_unregister_display(dssdev);
    303
    304	sharp_ls_disable(dssdev);
    305	sharp_ls_disconnect(dssdev);
    306
    307	omap_dss_put_device(in);
    308
    309	return 0;
    310}
    311
    312static const struct of_device_id sharp_ls_of_match[] = {
    313	{ .compatible = "omapdss,sharp,ls037v7dw01", },
    314	{},
    315};
    316
    317MODULE_DEVICE_TABLE(of, sharp_ls_of_match);
    318
    319static struct platform_driver sharp_ls_driver = {
    320	.probe = sharp_ls_probe,
    321	.remove = __exit_p(sharp_ls_remove),
    322	.driver = {
    323		.name = "panel-sharp-ls037v7dw01",
    324		.of_match_table = sharp_ls_of_match,
    325		.suppress_bind_attrs = true,
    326	},
    327};
    328
    329module_platform_driver(sharp_ls_driver);
    330
    331MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
    332MODULE_DESCRIPTION("Sharp LS037V7DW01 Panel Driver");
    333MODULE_LICENSE("GPL");