Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * Copyright (C) 2019, Amarula Solutions.
  4 * Author: Jagan Teki <jagan@amarulasolutions.com>
  5 */
  6
  7#include <drm/drm_mipi_dsi.h>
  8#include <drm/drm_modes.h>
  9#include <drm/drm_panel.h>
 10#include <drm/drm_print.h>
 11
 12#include <linux/backlight.h>
 13#include <linux/gpio/consumer.h>
 14#include <linux/delay.h>
 15#include <linux/module.h>
 16#include <linux/of_device.h>
 17#include <linux/regulator/consumer.h>
 18
 19#include <video/mipi_display.h>
 20
 21/* Command2 BKx selection command */
 22#define DSI_CMD2BKX_SEL			0xFF
 23
 24/* Command2, BK0 commands */
 25#define DSI_CMD2_BK0_PVGAMCTRL		0xB0 /* Positive Voltage Gamma Control */
 26#define DSI_CMD2_BK0_NVGAMCTRL		0xB1 /* Negative Voltage Gamma Control */
 27#define DSI_CMD2_BK0_LNESET		0xC0 /* Display Line setting */
 28#define DSI_CMD2_BK0_PORCTRL		0xC1 /* Porch control */
 29#define DSI_CMD2_BK0_INVSEL		0xC2 /* Inversion selection, Frame Rate Control */
 30
 31/* Command2, BK1 commands */
 32#define DSI_CMD2_BK1_VRHS		0xB0 /* Vop amplitude setting */
 33#define DSI_CMD2_BK1_VCOM		0xB1 /* VCOM amplitude setting */
 34#define DSI_CMD2_BK1_VGHSS		0xB2 /* VGH Voltage setting */
 35#define DSI_CMD2_BK1_TESTCMD		0xB3 /* TEST Command Setting */
 36#define DSI_CMD2_BK1_VGLS		0xB5 /* VGL Voltage setting */
 37#define DSI_CMD2_BK1_PWCTLR1		0xB7 /* Power Control 1 */
 38#define DSI_CMD2_BK1_PWCTLR2		0xB8 /* Power Control 2 */
 39#define DSI_CMD2_BK1_SPD1		0xC1 /* Source pre_drive timing set1 */
 40#define DSI_CMD2_BK1_SPD2		0xC2 /* Source EQ2 Setting */
 41#define DSI_CMD2_BK1_MIPISET1		0xD0 /* MIPI Setting 1 */
 42
 43/**
 44 * Command2 with BK function selection.
 45 *
 46 * BIT[4, 0]: [CN2, BKXSEL]
 47 * 10 = CMD2BK0, Command2 BK0
 48 * 11 = CMD2BK1, Command2 BK1
 49 * 00 = Command2 disable
 50 */
 51#define DSI_CMD2BK1_SEL			0x11
 52#define DSI_CMD2BK0_SEL			0x10
 53#define DSI_CMD2BKX_SEL_NONE		0x00
 54
 55/* Command2, BK0 bytes */
 56#define DSI_LINESET_LINE		0x69
 57#define DSI_LINESET_LDE_EN		BIT(7)
 58#define DSI_LINESET_LINEDELTA		GENMASK(1, 0)
 59#define DSI_CMD2_BK0_LNESET_B1		DSI_LINESET_LINEDELTA
 60#define DSI_CMD2_BK0_LNESET_B0		(DSI_LINESET_LDE_EN | DSI_LINESET_LINE)
 61#define DSI_INVSEL_DEFAULT		GENMASK(5, 4)
 62#define DSI_INVSEL_NLINV		GENMASK(2, 0)
 63#define DSI_INVSEL_RTNI			GENMASK(2, 1)
 64#define DSI_CMD2_BK0_INVSEL_B1		DSI_INVSEL_RTNI
 65#define DSI_CMD2_BK0_INVSEL_B0		(DSI_INVSEL_DEFAULT | DSI_INVSEL_NLINV)
 66#define DSI_CMD2_BK0_PORCTRL_B0(m)	((m)->vtotal - (m)->vsync_end)
 67#define DSI_CMD2_BK0_PORCTRL_B1(m)	((m)->vsync_start - (m)->vdisplay)
 68
 69/* Command2, BK1 bytes */
 70#define DSI_CMD2_BK1_VRHA_SET		0x45
 71#define DSI_CMD2_BK1_VCOM_SET		0x13
 72#define DSI_CMD2_BK1_VGHSS_SET		GENMASK(2, 0)
 73#define DSI_CMD2_BK1_TESTCMD_VAL	BIT(7)
 74#define DSI_VGLS_DEFAULT		BIT(6)
 75#define DSI_VGLS_SEL			GENMASK(2, 0)
 76#define DSI_CMD2_BK1_VGLS_SET		(DSI_VGLS_DEFAULT | DSI_VGLS_SEL)
 77#define DSI_PWCTLR1_AP			BIT(7) /* Gamma OP bias, max */
 78#define DSI_PWCTLR1_APIS		BIT(2) /* Source OP input bias, min */
 79#define DSI_PWCTLR1_APOS		BIT(0) /* Source OP output bias, min */
 80#define DSI_CMD2_BK1_PWCTLR1_SET	(DSI_PWCTLR1_AP | DSI_PWCTLR1_APIS | \
 81					DSI_PWCTLR1_APOS)
 82#define DSI_PWCTLR2_AVDD		BIT(5) /* AVDD 6.6v */
 83#define DSI_PWCTLR2_AVCL		0x0    /* AVCL -4.4v */
 84#define DSI_CMD2_BK1_PWCTLR2_SET	(DSI_PWCTLR2_AVDD | DSI_PWCTLR2_AVCL)
 85#define DSI_SPD1_T2D			BIT(3)
 86#define DSI_CMD2_BK1_SPD1_SET		(GENMASK(6, 4) | DSI_SPD1_T2D)
 87#define DSI_CMD2_BK1_SPD2_SET		DSI_CMD2_BK1_SPD1_SET
 88#define DSI_MIPISET1_EOT_EN		BIT(3)
 89#define DSI_CMD2_BK1_MIPISET1_SET	(BIT(7) | DSI_MIPISET1_EOT_EN)
 90
 91struct st7701_panel_desc {
 92	const struct drm_display_mode *mode;
 93	unsigned int lanes;
 94	unsigned long flags;
 95	enum mipi_dsi_pixel_format format;
 96	const char *const *supply_names;
 97	unsigned int num_supplies;
 98	unsigned int panel_sleep_delay;
 99};
100
101struct st7701 {
102	struct drm_panel panel;
103	struct mipi_dsi_device *dsi;
104	const struct st7701_panel_desc *desc;
105
106	struct backlight_device *backlight;
107	struct regulator_bulk_data *supplies;
108	struct gpio_desc *reset;
109	unsigned int sleep_delay;
110};
111
112static inline struct st7701 *panel_to_st7701(struct drm_panel *panel)
113{
114	return container_of(panel, struct st7701, panel);
115}
116
117static inline int st7701_dsi_write(struct st7701 *st7701, const void *seq,
118				   size_t len)
119{
120	return mipi_dsi_dcs_write_buffer(st7701->dsi, seq, len);
121}
122
123#define ST7701_DSI(st7701, seq...)				\
124	{							\
125		const u8 d[] = { seq };				\
126		st7701_dsi_write(st7701, d, ARRAY_SIZE(d));	\
127	}
128
129static void st7701_init_sequence(struct st7701 *st7701)
130{
131	const struct drm_display_mode *mode = st7701->desc->mode;
132
133	ST7701_DSI(st7701, MIPI_DCS_SOFT_RESET, 0x00);
134
135	/* We need to wait 5ms before sending new commands */
136	msleep(5);
137
138	ST7701_DSI(st7701, MIPI_DCS_EXIT_SLEEP_MODE, 0x00);
139
140	msleep(st7701->sleep_delay);
141
142	/* Command2, BK0 */
143	ST7701_DSI(st7701, DSI_CMD2BKX_SEL,
144		   0x77, 0x01, 0x00, 0x00, DSI_CMD2BK0_SEL);
145	ST7701_DSI(st7701, DSI_CMD2_BK0_PVGAMCTRL, 0x00, 0x0E, 0x15, 0x0F,
146		   0x11, 0x08, 0x08, 0x08, 0x08, 0x23, 0x04, 0x13, 0x12,
147		   0x2B, 0x34, 0x1F);
148	ST7701_DSI(st7701, DSI_CMD2_BK0_NVGAMCTRL, 0x00, 0x0E, 0x95, 0x0F,
149		   0x13, 0x07, 0x09, 0x08, 0x08, 0x22, 0x04, 0x10, 0x0E,
150		   0x2C, 0x34, 0x1F);
151	ST7701_DSI(st7701, DSI_CMD2_BK0_LNESET,
152		   DSI_CMD2_BK0_LNESET_B0, DSI_CMD2_BK0_LNESET_B1);
153	ST7701_DSI(st7701, DSI_CMD2_BK0_PORCTRL,
154		   DSI_CMD2_BK0_PORCTRL_B0(mode),
155		   DSI_CMD2_BK0_PORCTRL_B1(mode));
156	ST7701_DSI(st7701, DSI_CMD2_BK0_INVSEL,
157		   DSI_CMD2_BK0_INVSEL_B0, DSI_CMD2_BK0_INVSEL_B1);
158
159	/* Command2, BK1 */
160	ST7701_DSI(st7701, DSI_CMD2BKX_SEL,
161			0x77, 0x01, 0x00, 0x00, DSI_CMD2BK1_SEL);
162	ST7701_DSI(st7701, DSI_CMD2_BK1_VRHS, DSI_CMD2_BK1_VRHA_SET);
163	ST7701_DSI(st7701, DSI_CMD2_BK1_VCOM, DSI_CMD2_BK1_VCOM_SET);
164	ST7701_DSI(st7701, DSI_CMD2_BK1_VGHSS, DSI_CMD2_BK1_VGHSS_SET);
165	ST7701_DSI(st7701, DSI_CMD2_BK1_TESTCMD, DSI_CMD2_BK1_TESTCMD_VAL);
166	ST7701_DSI(st7701, DSI_CMD2_BK1_VGLS, DSI_CMD2_BK1_VGLS_SET);
167	ST7701_DSI(st7701, DSI_CMD2_BK1_PWCTLR1, DSI_CMD2_BK1_PWCTLR1_SET);
168	ST7701_DSI(st7701, DSI_CMD2_BK1_PWCTLR2, DSI_CMD2_BK1_PWCTLR2_SET);
169	ST7701_DSI(st7701, DSI_CMD2_BK1_SPD1, DSI_CMD2_BK1_SPD1_SET);
170	ST7701_DSI(st7701, DSI_CMD2_BK1_SPD2, DSI_CMD2_BK1_SPD2_SET);
171	ST7701_DSI(st7701, DSI_CMD2_BK1_MIPISET1, DSI_CMD2_BK1_MIPISET1_SET);
172
173	/**
174	 * ST7701_SPEC_V1.2 is unable to provide enough information above this
175	 * specific command sequence, so grab the same from vendor BSP driver.
176	 */
177	ST7701_DSI(st7701, 0xE0, 0x00, 0x00, 0x02);
178	ST7701_DSI(st7701, 0xE1, 0x0B, 0x00, 0x0D, 0x00, 0x0C, 0x00, 0x0E,
179		   0x00, 0x00, 0x44, 0x44);
180	ST7701_DSI(st7701, 0xE2, 0x33, 0x33, 0x44, 0x44, 0x64, 0x00, 0x66,
181		   0x00, 0x65, 0x00, 0x67, 0x00, 0x00);
182	ST7701_DSI(st7701, 0xE3, 0x00, 0x00, 0x33, 0x33);
183	ST7701_DSI(st7701, 0xE4, 0x44, 0x44);
184	ST7701_DSI(st7701, 0xE5, 0x0C, 0x78, 0x3C, 0xA0, 0x0E, 0x78, 0x3C,
185		   0xA0, 0x10, 0x78, 0x3C, 0xA0, 0x12, 0x78, 0x3C, 0xA0);
186	ST7701_DSI(st7701, 0xE6, 0x00, 0x00, 0x33, 0x33);
187	ST7701_DSI(st7701, 0xE7, 0x44, 0x44);
188	ST7701_DSI(st7701, 0xE8, 0x0D, 0x78, 0x3C, 0xA0, 0x0F, 0x78, 0x3C,
189		   0xA0, 0x11, 0x78, 0x3C, 0xA0, 0x13, 0x78, 0x3C, 0xA0);
190	ST7701_DSI(st7701, 0xEB, 0x02, 0x02, 0x39, 0x39, 0xEE, 0x44, 0x00);
191	ST7701_DSI(st7701, 0xEC, 0x00, 0x00);
192	ST7701_DSI(st7701, 0xED, 0xFF, 0xF1, 0x04, 0x56, 0x72, 0x3F, 0xFF,
193		   0xFF, 0xFF, 0xFF, 0xF3, 0x27, 0x65, 0x40, 0x1F, 0xFF);
194
195	/* disable Command2 */
196	ST7701_DSI(st7701, DSI_CMD2BKX_SEL,
197		   0x77, 0x01, 0x00, 0x00, DSI_CMD2BKX_SEL_NONE);
198}
199
200static int st7701_prepare(struct drm_panel *panel)
201{
202	struct st7701 *st7701 = panel_to_st7701(panel);
203	int ret;
204
205	gpiod_set_value(st7701->reset, 0);
206
207	ret = regulator_bulk_enable(st7701->desc->num_supplies,
208				    st7701->supplies);
209	if (ret < 0)
210		return ret;
211	msleep(20);
212
213	gpiod_set_value(st7701->reset, 1);
214	msleep(150);
215
216	st7701_init_sequence(st7701);
217
218	return 0;
219}
220
221static int st7701_enable(struct drm_panel *panel)
222{
223	struct st7701 *st7701 = panel_to_st7701(panel);
224
225	ST7701_DSI(st7701, MIPI_DCS_SET_DISPLAY_ON, 0x00);
226	backlight_enable(st7701->backlight);
227
228	return 0;
229}
230
231static int st7701_disable(struct drm_panel *panel)
232{
233	struct st7701 *st7701 = panel_to_st7701(panel);
234
235	backlight_disable(st7701->backlight);
236	ST7701_DSI(st7701, MIPI_DCS_SET_DISPLAY_OFF, 0x00);
237
238	return 0;
239}
240
241static int st7701_unprepare(struct drm_panel *panel)
242{
243	struct st7701 *st7701 = panel_to_st7701(panel);
244
245	ST7701_DSI(st7701, MIPI_DCS_ENTER_SLEEP_MODE, 0x00);
246
247	msleep(st7701->sleep_delay);
248
249	gpiod_set_value(st7701->reset, 0);
250
251	/**
252	 * During the Resetting period, the display will be blanked
253	 * (The display is entering blanking sequence, which maximum
254	 * time is 120 ms, when Reset Starts in Sleep Out –mode. The
255	 * display remains the blank state in Sleep In –mode.) and
256	 * then return to Default condition for Hardware Reset.
257	 *
258	 * So we need wait sleep_delay time to make sure reset completed.
259	 */
260	msleep(st7701->sleep_delay);
261
262	regulator_bulk_disable(st7701->desc->num_supplies, st7701->supplies);
263
264	return 0;
265}
266
267static int st7701_get_modes(struct drm_panel *panel)
268{
269	struct st7701 *st7701 = panel_to_st7701(panel);
270	const struct drm_display_mode *desc_mode = st7701->desc->mode;
271	struct drm_display_mode *mode;
272
273	mode = drm_mode_duplicate(panel->drm, desc_mode);
274	if (!mode) {
275		DRM_DEV_ERROR(&st7701->dsi->dev,
276			      "failed to add mode %ux%ux@%u\n",
277			      desc_mode->hdisplay, desc_mode->vdisplay,
278			      desc_mode->vrefresh);
279		return -ENOMEM;
280	}
281
282	drm_mode_set_name(mode);
283	drm_mode_probed_add(panel->connector, mode);
284
285	panel->connector->display_info.width_mm = desc_mode->width_mm;
286	panel->connector->display_info.height_mm = desc_mode->height_mm;
287
288	return 1;
289}
290
291static const struct drm_panel_funcs st7701_funcs = {
292	.disable	= st7701_disable,
293	.unprepare	= st7701_unprepare,
294	.prepare	= st7701_prepare,
295	.enable		= st7701_enable,
296	.get_modes	= st7701_get_modes,
297};
298
299static const struct drm_display_mode ts8550b_mode = {
300	.clock		= 27500,
301
302	.hdisplay	= 480,
303	.hsync_start	= 480 + 38,
304	.hsync_end	= 480 + 38 + 12,
305	.htotal		= 480 + 38 + 12 + 12,
306
307	.vdisplay	= 854,
308	.vsync_start	= 854 + 18,
309	.vsync_end	= 854 + 18 + 8,
310	.vtotal		= 854 + 18 + 8 + 4,
311
312	.width_mm	= 69,
313	.height_mm	= 139,
314
315	.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
316};
317
318static const char * const ts8550b_supply_names[] = {
319	"VCC",
320	"IOVCC",
321};
322
323static const struct st7701_panel_desc ts8550b_desc = {
324	.mode = &ts8550b_mode,
325	.lanes = 2,
326	.flags = MIPI_DSI_MODE_VIDEO,
327	.format = MIPI_DSI_FMT_RGB888,
328	.supply_names = ts8550b_supply_names,
329	.num_supplies = ARRAY_SIZE(ts8550b_supply_names),
330	.panel_sleep_delay = 80, /* panel need extra 80ms for sleep out cmd */
331};
332
333static int st7701_dsi_probe(struct mipi_dsi_device *dsi)
334{
335	const struct st7701_panel_desc *desc;
336	struct st7701 *st7701;
337	int ret, i;
338
339	st7701 = devm_kzalloc(&dsi->dev, sizeof(*st7701), GFP_KERNEL);
340	if (!st7701)
341		return -ENOMEM;
342
343	desc = of_device_get_match_data(&dsi->dev);
344	dsi->mode_flags = desc->flags;
345	dsi->format = desc->format;
346	dsi->lanes = desc->lanes;
347
348	st7701->supplies = devm_kcalloc(&dsi->dev, desc->num_supplies,
349					sizeof(*st7701->supplies),
350					GFP_KERNEL);
351	if (!st7701->supplies)
352		return -ENOMEM;
353
354	for (i = 0; i < desc->num_supplies; i++)
355		st7701->supplies[i].supply = desc->supply_names[i];
356
357	ret = devm_regulator_bulk_get(&dsi->dev, desc->num_supplies,
358				      st7701->supplies);
359	if (ret < 0)
360		return ret;
361
362	st7701->reset = devm_gpiod_get(&dsi->dev, "reset", GPIOD_OUT_LOW);
363	if (IS_ERR(st7701->reset)) {
364		DRM_DEV_ERROR(&dsi->dev, "Couldn't get our reset GPIO\n");
365		return PTR_ERR(st7701->reset);
366	}
367
368	st7701->backlight = devm_of_find_backlight(&dsi->dev);
369	if (IS_ERR(st7701->backlight))
370		return PTR_ERR(st7701->backlight);
371
372	drm_panel_init(&st7701->panel);
373
374	/**
375	 * Once sleep out has been issued, ST7701 IC required to wait 120ms
376	 * before initiating new commands.
377	 *
378	 * On top of that some panels might need an extra delay to wait, so
379	 * add panel specific delay for those cases. As now this panel specific
380	 * delay information is referenced from those panel BSP driver, example
381	 * ts8550b and there is no valid documentation for that.
382	 */
383	st7701->sleep_delay = 120 + desc->panel_sleep_delay;
384	st7701->panel.funcs = &st7701_funcs;
385	st7701->panel.dev = &dsi->dev;
386
387	ret = drm_panel_add(&st7701->panel);
388	if (ret < 0)
389		return ret;
390
391	mipi_dsi_set_drvdata(dsi, st7701);
392	st7701->dsi = dsi;
393	st7701->desc = desc;
394
395	return mipi_dsi_attach(dsi);
396}
397
398static int st7701_dsi_remove(struct mipi_dsi_device *dsi)
399{
400	struct st7701 *st7701 = mipi_dsi_get_drvdata(dsi);
401
402	mipi_dsi_detach(dsi);
403	drm_panel_remove(&st7701->panel);
404
405	return 0;
406}
407
408static const struct of_device_id st7701_of_match[] = {
409	{ .compatible = "techstar,ts8550b", .data = &ts8550b_desc },
410	{ }
411};
412MODULE_DEVICE_TABLE(of, st7701_of_match);
413
414static struct mipi_dsi_driver st7701_dsi_driver = {
415	.probe		= st7701_dsi_probe,
416	.remove		= st7701_dsi_remove,
417	.driver = {
418		.name		= "st7701",
419		.of_match_table	= st7701_of_match,
420	},
421};
422module_mipi_dsi_driver(st7701_dsi_driver);
423
424MODULE_AUTHOR("Jagan Teki <jagan@amarulasolutions.com>");
425MODULE_DESCRIPTION("Sitronix ST7701 LCD Panel Driver");
426MODULE_LICENSE("GPL");