GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / gpu / drm / panel / panel-samsung-s6d27a1.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Panel driver for the Samsung S6D27A1 480x800 DPI RGB panel.
4  * Found in the Samsung Galaxy Ace 2 GT-I8160 mobile phone.
5  */
6
7 #include <drm/drm_mipi_dbi.h>
8 #include <drm/drm_modes.h>
9 #include <drm/drm_panel.h>
10
11 #include <linux/delay.h>
12 #include <linux/gpio/consumer.h>
13 #include <linux/init.h>
14 #include <linux/kernel.h>
15 #include <linux/media-bus-format.h>
16 #include <linux/module.h>
17 #include <linux/of.h>
18 #include <linux/regulator/consumer.h>
19 #include <linux/spi/spi.h>
20
21 #include <video/mipi_display.h>
22
23 #define S6D27A1_PASSWD_L2       0xF0    /* Password Command for Level 2 Control */
24 #define S6D27A1_RESCTL          0xB3    /* Resolution Select Control */
25 #define S6D27A1_PANELCTL2       0xB4    /* ASG Signal Control */
26 #define S6D27A1_READID1         0xDA    /* Read panel ID 1 */
27 #define S6D27A1_READID2         0xDB    /* Read panel ID 2 */
28 #define S6D27A1_READID3         0xDC    /* Read panel ID 3 */
29 #define S6D27A1_DISPCTL         0xF2    /* Display Control */
30 #define S6D27A1_MANPWR          0xF3    /* Manual Control */
31 #define S6D27A1_PWRCTL1         0xF4    /* Power Control */
32 #define S6D27A1_SRCCTL          0xF6    /* Source Control */
33 #define S6D27A1_PANELCTL        0xF7    /* Panel Control*/
34
35 static const u8 s6d27a1_dbi_read_commands[] = {
36         S6D27A1_READID1,
37         S6D27A1_READID2,
38         S6D27A1_READID3,
39         0, /* sentinel */
40 };
41
42 struct s6d27a1 {
43         struct device *dev;
44         struct mipi_dbi dbi;
45         struct drm_panel panel;
46         struct gpio_desc *reset;
47         struct regulator_bulk_data regulators[2];
48 };
49
50 static const struct drm_display_mode s6d27a1_480_800_mode = {
51         /*
52          * The vendor driver states that the S6D27A1 panel
53          * has a pixel clock frequency of 49920000 Hz / 2 = 24960000 Hz.
54          */
55         .clock = 24960,
56         .hdisplay = 480,
57         .hsync_start = 480 + 63,
58         .hsync_end = 480 + 63 + 2,
59         .htotal = 480 + 63 + 2 + 63,
60         .vdisplay = 800,
61         .vsync_start = 800 + 11,
62         .vsync_end = 800 + 11 + 2,
63         .vtotal = 800 + 11 + 2 + 10,
64         .width_mm = 50,
65         .height_mm = 84,
66         .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
67 };
68
69 static inline struct s6d27a1 *to_s6d27a1(struct drm_panel *panel)
70 {
71         return container_of(panel, struct s6d27a1, panel);
72 }
73
74 static void s6d27a1_read_mtp_id(struct s6d27a1 *ctx)
75 {
76         struct mipi_dbi *dbi = &ctx->dbi;
77         u8 id1, id2, id3;
78         int ret;
79
80         ret = mipi_dbi_command_read(dbi, S6D27A1_READID1, &id1);
81         if (ret) {
82                 dev_err(ctx->dev, "unable to read MTP ID 1\n");
83                 return;
84         }
85         ret = mipi_dbi_command_read(dbi, S6D27A1_READID2, &id2);
86         if (ret) {
87                 dev_err(ctx->dev, "unable to read MTP ID 2\n");
88                 return;
89         }
90         ret = mipi_dbi_command_read(dbi, S6D27A1_READID3, &id3);
91         if (ret) {
92                 dev_err(ctx->dev, "unable to read MTP ID 3\n");
93                 return;
94         }
95         dev_info(ctx->dev, "MTP ID: %02x %02x %02x\n", id1, id2, id3);
96 }
97
98 static int s6d27a1_power_on(struct s6d27a1 *ctx)
99 {
100         struct mipi_dbi *dbi = &ctx->dbi;
101         int ret;
102
103         /* Power up */
104         ret = regulator_bulk_enable(ARRAY_SIZE(ctx->regulators),
105                                     ctx->regulators);
106         if (ret) {
107                 dev_err(ctx->dev, "failed to enable regulators: %d\n", ret);
108                 return ret;
109         }
110
111         msleep(20);
112
113         /* Assert reset >=1 ms */
114         gpiod_set_value_cansleep(ctx->reset, 1);
115         usleep_range(1000, 5000);
116         /* De-assert reset */
117         gpiod_set_value_cansleep(ctx->reset, 0);
118         /* Wait >= 10 ms */
119         msleep(20);
120
121         /*
122          * Exit sleep mode and initialize display - some hammering is
123          * necessary.
124          */
125         mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
126         mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
127         msleep(120);
128
129         /* Magic to unlock level 2 control of the display */
130         mipi_dbi_command(dbi, S6D27A1_PASSWD_L2, 0x5A, 0x5A);
131
132         /* Configure resolution to 480RGBx800 */
133         mipi_dbi_command(dbi, S6D27A1_RESCTL, 0x22);
134
135         mipi_dbi_command(dbi, S6D27A1_PANELCTL2, 0x00, 0x02, 0x03, 0x04, 0x05, 0x08, 0x00, 0x0c);
136
137         mipi_dbi_command(dbi, S6D27A1_MANPWR, 0x01, 0x00, 0x00, 0x08, 0x08, 0x02, 0x00);
138
139         mipi_dbi_command(dbi, S6D27A1_DISPCTL, 0x19, 0x00, 0x08, 0x0D, 0x03, 0x41, 0x3F);
140
141         mipi_dbi_command(dbi, S6D27A1_PWRCTL1, 0x00, 0x00, 0x00, 0x00, 0x55,
142                                         0x44, 0x05, 0x88, 0x4B, 0x50);
143
144         mipi_dbi_command(dbi, S6D27A1_SRCCTL, 0x03, 0x09, 0x8A, 0x00, 0x01, 0x16);
145
146         mipi_dbi_command(dbi, S6D27A1_PANELCTL, 0x00, 0x05, 0x06, 0x07, 0x08,
147                                         0x01, 0x09, 0x0D, 0x0A, 0x0E,
148                                         0x0B, 0x0F, 0x0C, 0x10, 0x01,
149                                         0x11, 0x12, 0x13, 0x14, 0x05,
150                                         0x06, 0x07, 0x08, 0x01, 0x09,
151                                         0x0D, 0x0A, 0x0E, 0x0B, 0x0F,
152                                         0x0C, 0x10, 0x01, 0x11, 0x12,
153                                         0x13, 0x14);
154
155         /* lock the level 2 control */
156         mipi_dbi_command(dbi, S6D27A1_PASSWD_L2, 0xA5, 0xA5);
157
158         s6d27a1_read_mtp_id(ctx);
159
160         return 0;
161 }
162
163 static int s6d27a1_power_off(struct s6d27a1 *ctx)
164 {
165         /* Go into RESET and disable regulators */
166         gpiod_set_value_cansleep(ctx->reset, 1);
167         return regulator_bulk_disable(ARRAY_SIZE(ctx->regulators),
168                                       ctx->regulators);
169 }
170
171 static int s6d27a1_unprepare(struct drm_panel *panel)
172 {
173         struct s6d27a1 *ctx = to_s6d27a1(panel);
174         struct mipi_dbi *dbi = &ctx->dbi;
175
176         mipi_dbi_command(dbi, MIPI_DCS_ENTER_SLEEP_MODE);
177         msleep(120);
178         return s6d27a1_power_off(to_s6d27a1(panel));
179 }
180
181 static int s6d27a1_disable(struct drm_panel *panel)
182 {
183         struct s6d27a1 *ctx = to_s6d27a1(panel);
184         struct mipi_dbi *dbi = &ctx->dbi;
185
186         mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_OFF);
187         msleep(25);
188
189         return 0;
190 }
191
192 static int s6d27a1_prepare(struct drm_panel *panel)
193 {
194         return s6d27a1_power_on(to_s6d27a1(panel));
195 }
196
197 static int s6d27a1_enable(struct drm_panel *panel)
198 {
199         struct s6d27a1 *ctx = to_s6d27a1(panel);
200         struct mipi_dbi *dbi = &ctx->dbi;
201
202         mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
203
204         return 0;
205 }
206
207 static int s6d27a1_get_modes(struct drm_panel *panel,
208                             struct drm_connector *connector)
209 {
210         struct s6d27a1 *ctx = to_s6d27a1(panel);
211         struct drm_display_mode *mode;
212         static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
213
214         mode = drm_mode_duplicate(connector->dev, &s6d27a1_480_800_mode);
215         if (!mode) {
216                 dev_err(ctx->dev, "failed to add mode\n");
217                 return -ENOMEM;
218         }
219
220         connector->display_info.bpc = 8;
221         connector->display_info.width_mm = mode->width_mm;
222         connector->display_info.height_mm = mode->height_mm;
223         connector->display_info.bus_flags =
224                 DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
225         drm_display_info_set_bus_formats(&connector->display_info,
226                                          &bus_format, 1);
227
228         drm_mode_set_name(mode);
229         mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
230
231         drm_mode_probed_add(connector, mode);
232
233         return 1;
234 }
235
236 static const struct drm_panel_funcs s6d27a1_drm_funcs = {
237         .disable = s6d27a1_disable,
238         .unprepare = s6d27a1_unprepare,
239         .prepare = s6d27a1_prepare,
240         .enable = s6d27a1_enable,
241         .get_modes = s6d27a1_get_modes,
242 };
243
244 static int s6d27a1_probe(struct spi_device *spi)
245 {
246         struct device *dev = &spi->dev;
247         struct s6d27a1 *ctx;
248         int ret;
249
250         ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
251         if (!ctx)
252                 return -ENOMEM;
253
254         ctx->dev = dev;
255
256         /*
257          * VCI   is the analog voltage supply
258          * VCCIO is the digital I/O voltage supply
259          */
260         ctx->regulators[0].supply = "vci";
261         ctx->regulators[1].supply = "vccio";
262         ret = devm_regulator_bulk_get(dev,
263                                       ARRAY_SIZE(ctx->regulators),
264                                       ctx->regulators);
265         if (ret)
266                 return dev_err_probe(dev, ret, "failed to get regulators\n");
267
268         ctx->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
269         if (IS_ERR(ctx->reset)) {
270                 ret = PTR_ERR(ctx->reset);
271                 return dev_err_probe(dev, ret, "no RESET GPIO\n");
272         }
273
274         ret = mipi_dbi_spi_init(spi, &ctx->dbi, NULL);
275         if (ret)
276                 return dev_err_probe(dev, ret, "MIPI DBI init failed\n");
277
278         ctx->dbi.read_commands = s6d27a1_dbi_read_commands;
279
280         drm_panel_init(&ctx->panel, dev, &s6d27a1_drm_funcs,
281                        DRM_MODE_CONNECTOR_DPI);
282
283         ret = drm_panel_of_backlight(&ctx->panel);
284         if (ret)
285                 return dev_err_probe(dev, ret, "failed to add backlight\n");
286
287         spi_set_drvdata(spi, ctx);
288
289         drm_panel_add(&ctx->panel);
290
291         return 0;
292 }
293
294 static void s6d27a1_remove(struct spi_device *spi)
295 {
296         struct s6d27a1 *ctx = spi_get_drvdata(spi);
297
298         drm_panel_remove(&ctx->panel);
299 }
300
301 static const struct of_device_id s6d27a1_match[] = {
302         { .compatible = "samsung,s6d27a1", },
303         { /* sentinel */ },
304 };
305 MODULE_DEVICE_TABLE(of, s6d27a1_match);
306
307 static struct spi_driver s6d27a1_driver = {
308         .probe          = s6d27a1_probe,
309         .remove         = s6d27a1_remove,
310         .driver         = {
311                 .name   = "s6d27a1-panel",
312                 .of_match_table = s6d27a1_match,
313         },
314 };
315 module_spi_driver(s6d27a1_driver);
316
317 MODULE_AUTHOR("Markuss Broks <markuss.broks@gmail.com>");
318 MODULE_DESCRIPTION("Samsung S6D27A1 panel driver");
319 MODULE_LICENSE("GPL v2");