1 // SPDX-License-Identifier: GPL-2.0
3 * DSI interface to the Samsung S6E63M0 panel.
4 * (C) 2019 Linus Walleij
7 #include <linux/module.h>
8 #include <linux/delay.h>
9 #include <linux/of_device.h>
11 #include <drm/drm_mipi_dsi.h>
12 #include <drm/drm_print.h>
14 #include "panel-samsung-s6e63m0.h"
16 #define MCS_GLOBAL_PARAM 0xb0
17 #define S6E63M0_DSI_MAX_CHUNK 15 /* CMD + 15 bytes max */
19 static int s6e63m0_dsi_dcs_read(struct device
*dev
, const u8 cmd
, u8
*data
)
21 struct mipi_dsi_device
*dsi
= to_mipi_dsi_device(dev
);
24 ret
= mipi_dsi_dcs_read(dsi
, cmd
, data
, 1);
26 dev_err(dev
, "could not read DCS CMD %02x\n", cmd
);
30 dev_info(dev
, "DSI read CMD %02x = %02x\n", cmd
, *data
);
35 static int s6e63m0_dsi_dcs_write(struct device
*dev
, const u8
*data
, size_t len
)
37 struct mipi_dsi_device
*dsi
= to_mipi_dsi_device(dev
);
38 const u8
*seqp
= data
;
45 dev_info(dev
, "DSI writing dcs seq: %*ph\n", (int)len
, data
);
47 /* Pick out and skip past the DCS command */
54 /* Send max S6E63M0_DSI_MAX_CHUNK bytes at a time */
55 if (chunk
> S6E63M0_DSI_MAX_CHUNK
)
56 chunk
= S6E63M0_DSI_MAX_CHUNK
;
57 ret
= mipi_dsi_dcs_write(dsi
, cmd
, seqp
, chunk
);
59 dev_err(dev
, "error sending DCS command seq cmd %02x\n", cmd
);
65 while (cmdwritten
< remain
) {
66 chunk
= remain
- cmdwritten
;
67 if (chunk
> S6E63M0_DSI_MAX_CHUNK
)
68 chunk
= S6E63M0_DSI_MAX_CHUNK
;
69 ret
= mipi_dsi_dcs_write(dsi
, MCS_GLOBAL_PARAM
, &cmdwritten
, 1);
71 dev_err(dev
, "error sending CMD %02x global param %02x\n",
75 ret
= mipi_dsi_dcs_write(dsi
, cmd
, seqp
, chunk
);
77 dev_err(dev
, "error sending CMD %02x chunk\n", cmd
);
83 dev_info(dev
, "sent command %02x %02x bytes\n", cmd
, cmdwritten
);
85 usleep_range(8000, 9000);
90 static int s6e63m0_dsi_probe(struct mipi_dsi_device
*dsi
)
92 struct device
*dev
= &dsi
->dev
;
96 dsi
->format
= MIPI_DSI_FMT_RGB888
;
97 dsi
->hs_rate
= 349440000;
98 dsi
->lp_rate
= 9600000;
99 dsi
->mode_flags
= MIPI_DSI_MODE_VIDEO
|
100 MIPI_DSI_MODE_EOT_PACKET
|
101 MIPI_DSI_MODE_VIDEO_BURST
;
103 ret
= s6e63m0_probe(dev
, s6e63m0_dsi_dcs_read
, s6e63m0_dsi_dcs_write
,
108 ret
= mipi_dsi_attach(dsi
);
115 static int s6e63m0_dsi_remove(struct mipi_dsi_device
*dsi
)
117 mipi_dsi_detach(dsi
);
118 return s6e63m0_remove(&dsi
->dev
);
121 static const struct of_device_id s6e63m0_dsi_of_match
[] = {
122 { .compatible
= "samsung,s6e63m0" },
125 MODULE_DEVICE_TABLE(of
, s6e63m0_dsi_of_match
);
127 static struct mipi_dsi_driver s6e63m0_dsi_driver
= {
128 .probe
= s6e63m0_dsi_probe
,
129 .remove
= s6e63m0_dsi_remove
,
131 .name
= "panel-samsung-s6e63m0",
132 .of_match_table
= s6e63m0_dsi_of_match
,
135 module_mipi_dsi_driver(s6e63m0_dsi_driver
);
137 MODULE_AUTHOR("Linus Walleij <linusw@kernel.org>");
138 MODULE_DESCRIPTION("s6e63m0 LCD DSI Driver");
139 MODULE_LICENSE("GPL v2");