1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2019, Huaqin Telecom Technology Co., Ltd
9 #include <linux/delay.h>
10 #include <linux/kernel.h>
11 #include <linux/module.h>
13 #include <linux/of_device.h>
15 #include <linux/gpio/consumer.h>
16 #include <linux/regulator/consumer.h>
18 #include <drm/drm_device.h>
19 #include <drm/drm_mipi_dsi.h>
20 #include <drm/drm_modes.h>
21 #include <drm/drm_panel.h>
22 #include <drm/drm_print.h>
24 #include <video/mipi_display.h>
32 const struct drm_display_mode *display_mode;
34 unsigned int width_mm;
35 unsigned int height_mm;
37 unsigned long mode_flags;
38 enum mipi_dsi_pixel_format format;
40 const struct panel_cmd *on_cmds;
41 unsigned int on_cmds_num;
45 struct drm_panel base;
46 struct mipi_dsi_device *link;
47 const struct panel_desc *desc;
49 struct gpio_desc *enable_gpio;
50 struct gpio_desc *pp33_gpio;
51 struct gpio_desc *pp18_gpio;
57 static inline struct panel_info *to_panel_info(struct drm_panel *panel)
59 return container_of(panel, struct panel_info, base);
62 static void disable_gpios(struct panel_info *pinfo)
64 gpiod_set_value(pinfo->enable_gpio, 0);
65 gpiod_set_value(pinfo->pp33_gpio, 0);
66 gpiod_set_value(pinfo->pp18_gpio, 0);
69 static int send_mipi_cmds(struct drm_panel *panel, const struct panel_cmd *cmds)
71 struct panel_info *pinfo = to_panel_info(panel);
75 for (i = 0; i < pinfo->desc->on_cmds_num; i++) {
76 err = mipi_dsi_dcs_write_buffer(pinfo->link, &cmds[i],
77 sizeof(struct panel_cmd));
86 static int boe_panel_disable(struct drm_panel *panel)
88 struct panel_info *pinfo = to_panel_info(panel);
94 err = mipi_dsi_dcs_set_display_off(pinfo->link);
96 DRM_DEV_ERROR(panel->dev, "failed to set display off: %d\n",
101 pinfo->enabled = false;
106 static int boe_panel_unprepare(struct drm_panel *panel)
108 struct panel_info *pinfo = to_panel_info(panel);
111 if (!pinfo->prepared)
114 err = mipi_dsi_dcs_set_display_off(pinfo->link);
116 DRM_DEV_ERROR(panel->dev, "failed to set display off: %d\n",
119 err = mipi_dsi_dcs_enter_sleep_mode(pinfo->link);
121 DRM_DEV_ERROR(panel->dev, "failed to enter sleep mode: %d\n",
124 /* sleep_mode_delay: 1ms - 2ms */
125 usleep_range(1000, 2000);
127 disable_gpios(pinfo);
129 pinfo->prepared = false;
134 static int boe_panel_prepare(struct drm_panel *panel)
136 struct panel_info *pinfo = to_panel_info(panel);
142 gpiod_set_value(pinfo->pp18_gpio, 1);
144 usleep_range(5000, 6000);
145 gpiod_set_value(pinfo->pp33_gpio, 1);
148 /* T2: 14ms - 15ms */
149 usleep_range(14000, 15000);
150 gpiod_set_value(pinfo->enable_gpio, 1);
153 usleep_range(1000, 2000);
154 gpiod_set_value(pinfo->enable_gpio, 0);
157 usleep_range(1000, 2000);
158 gpiod_set_value(pinfo->enable_gpio, 1);
161 usleep_range(5000, 6000);
164 err = send_mipi_cmds(panel, pinfo->desc->on_cmds);
166 DRM_DEV_ERROR(panel->dev, "failed to send DCS Init Code: %d\n",
171 err = mipi_dsi_dcs_exit_sleep_mode(pinfo->link);
173 DRM_DEV_ERROR(panel->dev, "failed to exit sleep mode: %d\n",
178 /* T6: 120ms - 121ms */
179 usleep_range(120000, 121000);
181 err = mipi_dsi_dcs_set_display_on(pinfo->link);
183 DRM_DEV_ERROR(panel->dev, "failed to set display on: %d\n",
188 /* T7: 20ms - 21ms */
189 usleep_range(20000, 21000);
191 pinfo->prepared = true;
196 disable_gpios(pinfo);
200 static int boe_panel_enable(struct drm_panel *panel)
202 struct panel_info *pinfo = to_panel_info(panel);
208 usleep_range(120000, 121000);
210 ret = mipi_dsi_dcs_set_display_on(pinfo->link);
212 DRM_DEV_ERROR(panel->dev, "failed to set display on: %d\n",
217 pinfo->enabled = true;
222 static int boe_panel_get_modes(struct drm_panel *panel,
223 struct drm_connector *connector)
225 struct panel_info *pinfo = to_panel_info(panel);
226 const struct drm_display_mode *m = pinfo->desc->display_mode;
227 struct drm_display_mode *mode;
229 mode = drm_mode_duplicate(connector->dev, m);
231 DRM_DEV_ERROR(pinfo->base.dev, "failed to add mode %ux%u@%u\n",
232 m->hdisplay, m->vdisplay, drm_mode_vrefresh(m));
236 drm_mode_set_name(mode);
238 drm_mode_probed_add(connector, mode);
240 connector->display_info.width_mm = pinfo->desc->width_mm;
241 connector->display_info.height_mm = pinfo->desc->height_mm;
242 connector->display_info.bpc = pinfo->desc->bpc;
247 static const struct drm_panel_funcs panel_funcs = {
248 .disable = boe_panel_disable,
249 .unprepare = boe_panel_unprepare,
250 .prepare = boe_panel_prepare,
251 .enable = boe_panel_enable,
252 .get_modes = boe_panel_get_modes,
255 static const struct drm_display_mode default_display_mode = {
258 .hsync_start = 1200 + 80,
259 .hsync_end = 1200 + 80 + 60,
260 .htotal = 1200 + 80 + 60 + 24,
262 .vsync_start = 1920 + 10,
263 .vsync_end = 1920 + 10 + 14,
264 .vtotal = 1920 + 10 + 14 + 4,
268 static const struct panel_cmd boe_himax8279d8p_on_cmds[] = {
531 static const struct panel_desc boe_himax8279d8p_panel_desc = {
532 .display_mode = &default_display_mode,
536 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
537 MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM,
538 .format = MIPI_DSI_FMT_RGB888,
540 .on_cmds = boe_himax8279d8p_on_cmds,
545 static const struct panel_cmd boe_himax8279d10p_on_cmds[] = {
831 static const struct panel_desc boe_himax8279d10p_panel_desc = {
832 .display_mode = &default_display_mode,
836 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
837 MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM,
838 .format = MIPI_DSI_FMT_RGB888,
840 .on_cmds = boe_himax8279d10p_on_cmds,
844 static const struct of_device_id panel_of_match[] = {
846 .compatible = "boe,himax8279d8p",
847 .data = &boe_himax8279d8p_panel_desc,
850 .compatible = "boe,himax8279d10p",
851 .data = &boe_himax8279d10p_panel_desc,
857 MODULE_DEVICE_TABLE(of, panel_of_match);
859 static int panel_add(struct panel_info *pinfo)
861 struct device *dev = &pinfo->link->dev;
864 pinfo->pp18_gpio = devm_gpiod_get(dev, "pp18", GPIOD_OUT_HIGH);
865 if (IS_ERR(pinfo->pp18_gpio)) {
866 ret = PTR_ERR(pinfo->pp18_gpio);
867 if (ret != -EPROBE_DEFER)
868 DRM_DEV_ERROR(dev, "failed to get pp18 gpio: %d\n",
873 pinfo->pp33_gpio = devm_gpiod_get(dev, "pp33", GPIOD_OUT_HIGH);
874 if (IS_ERR(pinfo->pp33_gpio)) {
875 ret = PTR_ERR(pinfo->pp33_gpio);
876 if (ret != -EPROBE_DEFER)
877 DRM_DEV_ERROR(dev, "failed to get pp33 gpio: %d\n",
882 pinfo->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
883 if (IS_ERR(pinfo->enable_gpio)) {
884 ret = PTR_ERR(pinfo->enable_gpio);
885 if (ret != -EPROBE_DEFER)
886 DRM_DEV_ERROR(dev, "failed to get enable gpio: %d\n",
891 drm_panel_init(&pinfo->base, dev, &panel_funcs,
892 DRM_MODE_CONNECTOR_DSI);
894 ret = drm_panel_of_backlight(&pinfo->base);
898 return drm_panel_add(&pinfo->base);
901 static int panel_probe(struct mipi_dsi_device *dsi)
903 struct panel_info *pinfo;
904 const struct panel_desc *desc;
907 pinfo = devm_kzalloc(&dsi->dev, sizeof(*pinfo), GFP_KERNEL);
911 desc = of_device_get_match_data(&dsi->dev);
912 dsi->mode_flags = desc->mode_flags;
913 dsi->format = desc->format;
914 dsi->lanes = desc->lanes;
918 mipi_dsi_set_drvdata(dsi, pinfo);
920 err = panel_add(pinfo);
924 err = mipi_dsi_attach(dsi);
926 drm_panel_remove(&pinfo->base);
931 static int panel_remove(struct mipi_dsi_device *dsi)
933 struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi);
936 err = boe_panel_disable(&pinfo->base);
938 DRM_DEV_ERROR(&dsi->dev, "failed to disable panel: %d\n",
941 err = boe_panel_unprepare(&pinfo->base);
943 DRM_DEV_ERROR(&dsi->dev, "failed to unprepare panel: %d\n",
946 err = mipi_dsi_detach(dsi);
948 DRM_DEV_ERROR(&dsi->dev, "failed to detach from DSI host: %d\n",
951 drm_panel_remove(&pinfo->base);
956 static void panel_shutdown(struct mipi_dsi_device *dsi)
958 struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi);
960 boe_panel_disable(&pinfo->base);
961 boe_panel_unprepare(&pinfo->base);
964 static struct mipi_dsi_driver panel_driver = {
966 .name = "panel-boe-himax8279d",
967 .of_match_table = panel_of_match,
969 .probe = panel_probe,
970 .remove = panel_remove,
971 .shutdown = panel_shutdown,
973 module_mipi_dsi_driver(panel_driver);
976 MODULE_DESCRIPTION("Boe Himax8279d driver");
977 MODULE_LICENSE("GPL v2");