Skip to content

Commit 1616bc2

Browse files
bivvyrkhuangtao
authored andcommitted
drm/panel: support transmit DSI packet
Change-Id: I6115479eebc05b44a8c01cd72919db0e5a6cb1f9 Signed-off-by: WeiYong Bi <bivvy.bi@rock-chips.com>
1 parent 8e85358 commit 1616bc2

2 files changed

Lines changed: 255 additions & 1 deletion

File tree

Documentation/devicetree/bindings/display/panel/simple-panel.txt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,18 @@ Optional properties when compatible is a dsi devices:
1919
- dsi,flags: dsi operation mode related flags
2020
- dsi,format: pixel format for video mode
2121
- dsi,lanes: number of active data lanes
22+
- reset-gpios: GPIO pin to reset the panel
23+
- reset-delay-ms: reset pulse width
24+
- panel-init-sequence: A byte stream formed by simple multiple dcs packets.
25+
byte 0: dcs data type
26+
byte 1: wait number of specified ms after dcs command transmitted
27+
byte 2, 3: 16 bits length in network byte order
28+
byte 4 and beyond: number byte of payload
29+
- panel-exit-sequence: A byte stream formed by simple multiple dcs packets.
30+
byte 0: dcs data type
31+
byte 1: wait number of specified ms after dcs command transmitted
32+
byte 2, 3: 16 bits length in network byte order
33+
byte 4 and beyond: number byte of payload
2234

2335
Example:
2436

@@ -40,6 +52,9 @@ Or:
4052
power-supply = <&vdd_pnl_reg>;
4153
enable-gpios = <&gpio 90 0>;
4254

55+
reset-gpios = <&gpio 91 0>;
56+
reset-delay-ms = <20>;
57+
4358
backlight = <&backlight>;
4459

4560
dsi,flags = <MIPI_DSI_MODE_VIDEO |
@@ -48,6 +63,19 @@ Or:
4863
dsi,format = <MIPI_DSI_FMT_RGB888>;
4964
dsi,lanes = <4>;
5065

66+
panel-init-sequence = [
67+
39 00 00 10 b1 6c 15 15 24 E4 11 f1 80 e4
68+
d7 23 80 c0 d2 58
69+
...
70+
05 78 00 01 11
71+
05 00 00 01 29
72+
];
73+
74+
panel-exit-sequence = [
75+
05 00 00 01 28
76+
05 78 00 01 10
77+
];
78+
5179
display-timings {
5280
native-mode = <&timing0>;
5381
timing0: timing0 {

drivers/gpu/drm/panel/panel-simple.c

Lines changed: 227 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,28 @@
3434
#include <drm/drm_panel.h>
3535

3636
#include <video/display_timing.h>
37+
#include <video/mipi_display.h>
3738
#include <video/of_display_timing.h>
3839
#include <video/videomode.h>
3940

41+
struct dsi_ctrl_hdr {
42+
u8 dtype; /* data type */
43+
u8 wait; /* ms */
44+
u16 dlen; /* payload len */
45+
} __packed;
46+
47+
struct dsi_cmd_desc {
48+
struct dsi_ctrl_hdr dchdr;
49+
u8 *payload;
50+
};
51+
52+
struct dsi_panel_cmds {
53+
u8 *buf;
54+
int blen;
55+
struct dsi_cmd_desc *cmds;
56+
int cmd_cnt;
57+
};
58+
4059
struct panel_desc {
4160
const struct drm_display_mode *modes;
4261
unsigned int num_modes;
@@ -73,6 +92,7 @@ struct panel_desc {
7392

7493
struct panel_simple {
7594
struct drm_panel base;
95+
struct mipi_dsi_device *dsi;
7696
bool prepared;
7797
bool enabled;
7898

@@ -84,13 +104,143 @@ struct panel_simple {
84104
struct i2c_adapter *ddc;
85105

86106
struct gpio_desc *enable_gpio;
107+
struct gpio_desc *reset_gpio;
108+
unsigned int reset_delay;
109+
110+
struct dsi_panel_cmds *on_cmds;
111+
struct dsi_panel_cmds *off_cmds;
87112
};
88113

89114
static inline struct panel_simple *to_panel_simple(struct drm_panel *panel)
90115
{
91116
return container_of(panel, struct panel_simple, base);
92117
}
93118

119+
static void panel_simple_dsi_cmds_cleanup(struct panel_simple *p)
120+
{
121+
if (p->on_cmds) {
122+
kfree(p->on_cmds->buf);
123+
kfree(p->on_cmds->cmds);
124+
}
125+
126+
if (p->off_cmds) {
127+
kfree(p->off_cmds->buf);
128+
kfree(p->off_cmds->cmds);
129+
}
130+
}
131+
132+
static int panel_simple_dsi_parse_dcs_cmds(struct device *dev,
133+
const u8 *data, int blen,
134+
struct dsi_panel_cmds *pcmds)
135+
{
136+
int len;
137+
char *buf, *bp;
138+
struct dsi_ctrl_hdr *dchdr;
139+
int i, cnt;
140+
141+
if (!pcmds)
142+
return -EINVAL;
143+
144+
buf = kmemdup(data, blen, GFP_KERNEL);
145+
if (!buf)
146+
return -ENOMEM;
147+
148+
/* scan dcs commands */
149+
bp = buf;
150+
len = blen;
151+
cnt = 0;
152+
while (len > sizeof(*dchdr)) {
153+
dchdr = (struct dsi_ctrl_hdr *)bp;
154+
dchdr->dlen = ntohs(dchdr->dlen);
155+
156+
if (dchdr->dlen > len) {
157+
dev_err(dev, "%s: error, len=%d", __func__,
158+
dchdr->dlen);
159+
return -EINVAL;
160+
}
161+
162+
bp += sizeof(*dchdr);
163+
len -= sizeof(*dchdr);
164+
bp += dchdr->dlen;
165+
len -= dchdr->dlen;
166+
cnt++;
167+
}
168+
169+
if (len != 0) {
170+
dev_err(dev, "%s: dcs_cmd=%x len=%d error!",
171+
__func__, buf[0], blen);
172+
kfree(buf);
173+
return -EINVAL;
174+
}
175+
176+
pcmds->cmds = kcalloc(cnt, sizeof(struct dsi_cmd_desc), GFP_KERNEL);
177+
if (!pcmds->cmds) {
178+
kfree(buf);
179+
return -ENOMEM;
180+
}
181+
182+
pcmds->cmd_cnt = cnt;
183+
pcmds->buf = buf;
184+
pcmds->blen = blen;
185+
186+
bp = buf;
187+
len = blen;
188+
for (i = 0; i < cnt; i++) {
189+
dchdr = (struct dsi_ctrl_hdr *)bp;
190+
len -= sizeof(*dchdr);
191+
bp += sizeof(*dchdr);
192+
pcmds->cmds[i].dchdr = *dchdr;
193+
pcmds->cmds[i].payload = bp;
194+
bp += dchdr->dlen;
195+
len -= dchdr->dlen;
196+
}
197+
198+
dev_info(dev, "%s: dcs_cmd=%x len=%d, cmd_cnt=%d\n", __func__,
199+
pcmds->buf[0], pcmds->blen, pcmds->cmd_cnt);
200+
return 0;
201+
}
202+
203+
static int panel_simple_dsi_send_cmds(struct panel_simple *panel,
204+
struct dsi_panel_cmds *cmds)
205+
{
206+
struct mipi_dsi_device *dsi = panel->dsi;
207+
int i, err;
208+
209+
if (!cmds)
210+
return -EINVAL;
211+
212+
for (i = 0; i < cmds->cmd_cnt; i++) {
213+
struct dsi_cmd_desc *cmd = &cmds->cmds[i];
214+
215+
switch (cmd->dchdr.dtype) {
216+
case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
217+
case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
218+
case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
219+
case MIPI_DSI_GENERIC_LONG_WRITE:
220+
err = mipi_dsi_generic_write(dsi, cmd->payload,
221+
cmd->dchdr.dlen);
222+
break;
223+
case MIPI_DSI_DCS_SHORT_WRITE:
224+
case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
225+
case MIPI_DSI_DCS_LONG_WRITE:
226+
err = mipi_dsi_dcs_write_buffer(dsi, cmd->payload,
227+
cmd->dchdr.dlen);
228+
break;
229+
default:
230+
return -EINVAL;
231+
}
232+
233+
if (err)
234+
dev_err(panel->dev, "failed to write dcs cmd: %d\n",
235+
err);
236+
237+
if (cmd->dchdr.wait)
238+
msleep(cmd->dchdr.wait);
239+
}
240+
241+
return 0;
242+
}
243+
94244
static int panel_simple_get_fixed_modes(struct panel_simple *panel)
95245
{
96246
struct drm_connector *connector = panel->base.connector;
@@ -204,10 +354,20 @@ static int panel_simple_disable(struct drm_panel *panel)
204354
static int panel_simple_unprepare(struct drm_panel *panel)
205355
{
206356
struct panel_simple *p = to_panel_simple(panel);
357+
int err;
207358

208359
if (!p->prepared)
209360
return 0;
210361

362+
if (p->off_cmds) {
363+
err = panel_simple_dsi_send_cmds(p, p->off_cmds);
364+
if (err)
365+
dev_err(p->dev, "failed to send off cmds\n");
366+
}
367+
368+
if (p->reset_gpio)
369+
gpiod_direction_output(p->reset_gpio, 1);
370+
211371
if (p->enable_gpio)
212372
gpiod_direction_output(p->enable_gpio, 0);
213373

@@ -241,6 +401,15 @@ static int panel_simple_prepare(struct drm_panel *panel)
241401
if (p->desc && p->desc->delay.prepare)
242402
msleep(p->desc->delay.prepare);
243403

404+
if (p->reset_gpio)
405+
gpiod_direction_output(p->reset_gpio, 1);
406+
407+
if (p->reset_delay)
408+
msleep(p->reset_delay);
409+
410+
if (p->reset_gpio)
411+
gpiod_direction_output(p->reset_gpio, 0);
412+
244413
p->prepared = true;
245414

246415
return 0;
@@ -249,10 +418,17 @@ static int panel_simple_prepare(struct drm_panel *panel)
249418
static int panel_simple_enable(struct drm_panel *panel)
250419
{
251420
struct panel_simple *p = to_panel_simple(panel);
421+
int err;
252422

253423
if (p->enabled)
254424
return 0;
255425

426+
if (p->on_cmds) {
427+
err = panel_simple_dsi_send_cmds(p, p->on_cmds);
428+
if (err)
429+
dev_err(p->dev, "failed to send on cmds\n");
430+
}
431+
256432
if (p->desc && p->desc->delay.enable)
257433
msleep(p->desc->delay.enable);
258434

@@ -359,7 +535,14 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
359535
panel->enable_gpio = devm_gpiod_get_optional(dev, "enable", 0);
360536
if (IS_ERR(panel->enable_gpio)) {
361537
err = PTR_ERR(panel->enable_gpio);
362-
dev_err(dev, "failed to request GPIO: %d\n", err);
538+
dev_err(dev, "failed to request enable GPIO: %d\n", err);
539+
return err;
540+
}
541+
542+
panel->reset_gpio = devm_gpiod_get_optional(dev, "reset", 0);
543+
if (IS_ERR(panel->reset_gpio)) {
544+
err = PTR_ERR(panel->reset_gpio);
545+
dev_err(dev, "failed to request reset GPIO: %d\n", err);
363546
return err;
364547
}
365548

@@ -420,6 +603,8 @@ static int panel_simple_remove(struct device *dev)
420603
if (panel->backlight)
421604
put_device(&panel->backlight->dev);
422605

606+
panel_simple_dsi_cmds_cleanup(panel);
607+
423608
return 0;
424609
}
425610

@@ -1718,9 +1903,12 @@ MODULE_DEVICE_TABLE(of, dsi_of_match);
17181903

17191904
static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi)
17201905
{
1906+
struct panel_simple *panel;
17211907
const struct panel_desc_dsi *desc;
17221908
const struct of_device_id *id;
17231909
const struct panel_desc *pdesc;
1910+
const void *data;
1911+
int len;
17241912
u32 val;
17251913
int err;
17261914

@@ -1743,6 +1931,9 @@ static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi)
17431931
if (err < 0)
17441932
return err;
17451933

1934+
panel = dev_get_drvdata(&dsi->dev);
1935+
panel->dsi = dsi;
1936+
17461937
if (!of_property_read_u32(dsi->dev.of_node, "dsi,flags", &val))
17471938
dsi->mode_flags = val;
17481939

@@ -1752,6 +1943,41 @@ static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi)
17521943
if (!of_property_read_u32(dsi->dev.of_node, "dsi,lanes", &val))
17531944
dsi->lanes = val;
17541945

1946+
if (!of_property_read_u32(dsi->dev.of_node, "reset-delay-ms", &val))
1947+
panel->reset_delay = val;
1948+
1949+
data = of_get_property(dsi->dev.of_node, "panel-init-sequence", &len);
1950+
if (data) {
1951+
panel->on_cmds = devm_kzalloc(&dsi->dev,
1952+
sizeof(*panel->on_cmds),
1953+
GFP_KERNEL);
1954+
if (!panel->on_cmds)
1955+
return -ENOMEM;
1956+
1957+
err = panel_simple_dsi_parse_dcs_cmds(&dsi->dev, data, len,
1958+
panel->on_cmds);
1959+
if (err) {
1960+
dev_err(&dsi->dev, "failed to parse panel init sequence\n");
1961+
return err;
1962+
}
1963+
}
1964+
1965+
data = of_get_property(dsi->dev.of_node, "panel-exit-sequence", &len);
1966+
if (data) {
1967+
panel->off_cmds = devm_kzalloc(&dsi->dev,
1968+
sizeof(*panel->off_cmds),
1969+
GFP_KERNEL);
1970+
if (!panel->off_cmds)
1971+
return -ENOMEM;
1972+
1973+
err = panel_simple_dsi_parse_dcs_cmds(&dsi->dev, data, len,
1974+
panel->off_cmds);
1975+
if (err) {
1976+
dev_err(&dsi->dev, "failed to parse panel exit sequence\n");
1977+
return err;
1978+
}
1979+
}
1980+
17551981
return mipi_dsi_attach(dsi);
17561982
}
17571983

0 commit comments

Comments
 (0)