xref: /linux/drivers/gpu/drm/panel/panel-samsung-s6d27a1.c (revision 260f6f4fda93c8485c8037865c941b42b9cba5d2)
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 
to_s6d27a1(struct drm_panel * panel)69 static inline struct s6d27a1 *to_s6d27a1(struct drm_panel *panel)
70 {
71 	return container_of(panel, struct s6d27a1, panel);
72 }
73 
s6d27a1_read_mtp_id(struct s6d27a1 * ctx)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 
s6d27a1_power_on(struct s6d27a1 * ctx)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 
s6d27a1_power_off(struct s6d27a1 * ctx)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 
s6d27a1_unprepare(struct drm_panel * panel)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 
s6d27a1_disable(struct drm_panel * panel)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 
s6d27a1_prepare(struct drm_panel * panel)192 static int s6d27a1_prepare(struct drm_panel *panel)
193 {
194 	return s6d27a1_power_on(to_s6d27a1(panel));
195 }
196 
s6d27a1_enable(struct drm_panel * panel)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 
s6d27a1_get_modes(struct drm_panel * panel,struct drm_connector * connector)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 
s6d27a1_probe(struct spi_device * spi)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_drm_panel_alloc(dev, struct s6d27a1, panel,
251 				   &s6d27a1_drm_funcs,
252 				   DRM_MODE_CONNECTOR_DPI);
253 	if (IS_ERR(ctx))
254 		return PTR_ERR(ctx);
255 
256 	ctx->dev = dev;
257 
258 	/*
259 	 * VCI   is the analog voltage supply
260 	 * VCCIO is the digital I/O voltage supply
261 	 */
262 	ctx->regulators[0].supply = "vci";
263 	ctx->regulators[1].supply = "vccio";
264 	ret = devm_regulator_bulk_get(dev,
265 				      ARRAY_SIZE(ctx->regulators),
266 				      ctx->regulators);
267 	if (ret)
268 		return dev_err_probe(dev, ret, "failed to get regulators\n");
269 
270 	ctx->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
271 	if (IS_ERR(ctx->reset)) {
272 		ret = PTR_ERR(ctx->reset);
273 		return dev_err_probe(dev, ret, "no RESET GPIO\n");
274 	}
275 
276 	ret = mipi_dbi_spi_init(spi, &ctx->dbi, NULL);
277 	if (ret)
278 		return dev_err_probe(dev, ret, "MIPI DBI init failed\n");
279 
280 	ctx->dbi.read_commands = s6d27a1_dbi_read_commands;
281 
282 	ret = drm_panel_of_backlight(&ctx->panel);
283 	if (ret)
284 		return dev_err_probe(dev, ret, "failed to add backlight\n");
285 
286 	spi_set_drvdata(spi, ctx);
287 
288 	drm_panel_add(&ctx->panel);
289 
290 	return 0;
291 }
292 
s6d27a1_remove(struct spi_device * spi)293 static void s6d27a1_remove(struct spi_device *spi)
294 {
295 	struct s6d27a1 *ctx = spi_get_drvdata(spi);
296 
297 	drm_panel_remove(&ctx->panel);
298 }
299 
300 static const struct of_device_id s6d27a1_match[] = {
301 	{ .compatible = "samsung,s6d27a1", },
302 	{ /* sentinel */ },
303 };
304 MODULE_DEVICE_TABLE(of, s6d27a1_match);
305 
306 static struct spi_driver s6d27a1_driver = {
307 	.probe		= s6d27a1_probe,
308 	.remove		= s6d27a1_remove,
309 	.driver		= {
310 		.name	= "s6d27a1-panel",
311 		.of_match_table = s6d27a1_match,
312 	},
313 };
314 module_spi_driver(s6d27a1_driver);
315 
316 MODULE_AUTHOR("Markuss Broks <markuss.broks@gmail.com>");
317 MODULE_DESCRIPTION("Samsung S6D27A1 panel driver");
318 MODULE_LICENSE("GPL v2");
319