Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / drivers / video / fbdev / mmp / panel / tpo_tj032md01bw.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * linux/drivers/video/mmp/panel/tpo_tj032md01bw.c
4  * active panel using spi interface to do init
5  *
6  * Copyright (C) 2012 Marvell Technology Group Ltd.
7  * Authors:  Guoqing Li <ligq@marvell.com>
8  *          Lisa Du <cldu@marvell.com>
9  *          Zhou Zhu <zzhu3@marvell.com>
10  */
11
12 #include <linux/module.h>
13 #include <linux/moduleparam.h>
14 #include <linux/kernel.h>
15 #include <linux/errno.h>
16 #include <linux/string.h>
17 #include <linux/delay.h>
18 #include <linux/platform_device.h>
19 #include <linux/err.h>
20 #include <linux/spi/spi.h>
21 #include <video/mmp_disp.h>
22
23 static u16 init[] = {
24         0x0801,
25         0x0800,
26         0x0200,
27         0x0304,
28         0x040e,
29         0x0903,
30         0x0b18,
31         0x0c53,
32         0x0d01,
33         0x0ee0,
34         0x0f01,
35         0x1058,
36         0x201e,
37         0x210a,
38         0x220a,
39         0x231e,
40         0x2400,
41         0x2532,
42         0x2600,
43         0x27ac,
44         0x2904,
45         0x2aa2,
46         0x2b45,
47         0x2c45,
48         0x2d15,
49         0x2e5a,
50         0x2fff,
51         0x306b,
52         0x310d,
53         0x3248,
54         0x3382,
55         0x34bd,
56         0x35e7,
57         0x3618,
58         0x3794,
59         0x3801,
60         0x395d,
61         0x3aae,
62         0x3bff,
63         0x07c9,
64 };
65
66 static u16 poweroff[] = {
67         0x07d9,
68 };
69
70 struct tpohvga_plat_data {
71         void (*plat_onoff)(int status);
72         struct spi_device *spi;
73 };
74
75 static void tpohvga_onoff(struct mmp_panel *panel, int status)
76 {
77         struct tpohvga_plat_data *plat = panel->plat_data;
78         int ret;
79
80         if (status) {
81                 plat->plat_onoff(1);
82
83                 ret = spi_write(plat->spi, init, sizeof(init));
84                 if (ret < 0)
85                         dev_warn(panel->dev, "init cmd failed(%d)\n", ret);
86         } else {
87                 ret = spi_write(plat->spi, poweroff, sizeof(poweroff));
88                 if (ret < 0)
89                         dev_warn(panel->dev, "poweroff cmd failed(%d)\n", ret);
90
91                 plat->plat_onoff(0);
92         }
93 }
94
95 static struct mmp_mode mmp_modes_tpohvga[] = {
96         [0] = {
97                 .pixclock_freq = 10394400,
98                 .refresh = 60,
99                 .xres = 320,
100                 .yres = 480,
101                 .hsync_len = 10,
102                 .left_margin = 15,
103                 .right_margin = 10,
104                 .vsync_len = 2,
105                 .upper_margin = 4,
106                 .lower_margin = 2,
107                 .invert_pixclock = 1,
108                 .pix_fmt_out = PIXFMT_RGB565,
109         },
110 };
111
112 static int tpohvga_get_modelist(struct mmp_panel *panel,
113                 struct mmp_mode **modelist)
114 {
115         *modelist = mmp_modes_tpohvga;
116         return 1;
117 }
118
119 static struct mmp_panel panel_tpohvga = {
120         .name = "tpohvga",
121         .panel_type = PANELTYPE_ACTIVE,
122         .get_modelist = tpohvga_get_modelist,
123         .set_onoff = tpohvga_onoff,
124 };
125
126 static int tpohvga_probe(struct spi_device *spi)
127 {
128         struct mmp_mach_panel_info *mi;
129         int ret;
130         struct tpohvga_plat_data *plat_data;
131
132         /* get configs from platform data */
133         mi = spi->dev.platform_data;
134         if (mi == NULL) {
135                 dev_err(&spi->dev, "%s: no platform data defined\n", __func__);
136                 return -EINVAL;
137         }
138
139         /* setup spi related info */
140         spi->bits_per_word = 16;
141         ret = spi_setup(spi);
142         if (ret < 0) {
143                 dev_err(&spi->dev, "spi setup failed %d", ret);
144                 return ret;
145         }
146
147         plat_data = kzalloc(sizeof(*plat_data), GFP_KERNEL);
148         if (plat_data == NULL)
149                 return -ENOMEM;
150
151         plat_data->spi = spi;
152         plat_data->plat_onoff = mi->plat_set_onoff;
153         panel_tpohvga.plat_data = plat_data;
154         panel_tpohvga.plat_path_name = mi->plat_path_name;
155         panel_tpohvga.dev = &spi->dev;
156
157         mmp_register_panel(&panel_tpohvga);
158
159         return 0;
160 }
161
162 static struct spi_driver panel_tpohvga_driver = {
163         .driver         = {
164                 .name   = "tpo-hvga",
165         },
166         .probe          = tpohvga_probe,
167 };
168 module_spi_driver(panel_tpohvga_driver);
169
170 MODULE_AUTHOR("Lisa Du<cldu@marvell.com>");
171 MODULE_DESCRIPTION("Panel driver for tpohvga");
172 MODULE_LICENSE("GPL");