Author | Tokens | Token Proportion | Commits | Commit Proportion |
---|---|---|---|---|
Jerry Han | 5079 | 100.00% | 1 | 100.00% |
Total | 5079 | 1 |
// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2019, Huaqin Telecom Technology Co., Ltd * * Author: Jerry Han <jerry.han.hq@gmail.com> * */ #include <linux/delay.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/gpio/consumer.h> #include <linux/regulator/consumer.h> #include <drm/drm_device.h> #include <drm/drm_mipi_dsi.h> #include <drm/drm_modes.h> #include <drm/drm_panel.h> #include <drm/drm_print.h> #include <video/mipi_display.h> struct panel_cmd { char cmd; char data; }; struct panel_desc { const struct drm_display_mode *display_mode; unsigned int bpc; unsigned int width_mm; unsigned int height_mm; unsigned long mode_flags; enum mipi_dsi_pixel_format format; unsigned int lanes; const struct panel_cmd *on_cmds; unsigned int on_cmds_num; }; struct panel_info { struct drm_panel base; struct mipi_dsi_device *link; const struct panel_desc *desc; struct gpio_desc *enable_gpio; struct gpio_desc *pp33_gpio; struct gpio_desc *pp18_gpio; bool prepared; bool enabled; }; static inline struct panel_info *to_panel_info(struct drm_panel *panel) { return container_of(panel, struct panel_info, base); } static void disable_gpios(struct panel_info *pinfo) { gpiod_set_value(pinfo->enable_gpio, 0); gpiod_set_value(pinfo->pp33_gpio, 0); gpiod_set_value(pinfo->pp18_gpio, 0); } static int send_mipi_cmds(struct drm_panel *panel, const struct panel_cmd *cmds) { struct panel_info *pinfo = to_panel_info(panel); unsigned int i = 0; int err; for (i = 0; i < pinfo->desc->on_cmds_num; i++) { err = mipi_dsi_dcs_write_buffer(pinfo->link, &cmds[i], sizeof(struct panel_cmd)); if (err < 0) return err; } return 0; } static int boe_panel_disable(struct drm_panel *panel) { struct panel_info *pinfo = to_panel_info(panel); int err; if (!pinfo->enabled) return 0; err = mipi_dsi_dcs_set_display_off(pinfo->link); if (err < 0) { DRM_DEV_ERROR(panel->dev, "failed to set display off: %d\n", err); return err; } pinfo->enabled = false; return 0; } static int boe_panel_unprepare(struct drm_panel *panel) { struct panel_info *pinfo = to_panel_info(panel); int err; if (!pinfo->prepared) return 0; err = mipi_dsi_dcs_set_display_off(pinfo->link); if (err < 0) DRM_DEV_ERROR(panel->dev, "failed to set display off: %d\n", err); err = mipi_dsi_dcs_enter_sleep_mode(pinfo->link); if (err < 0) DRM_DEV_ERROR(panel->dev, "failed to enter sleep mode: %d\n", err); /* sleep_mode_delay: 1ms - 2ms */ usleep_range(1000, 2000); disable_gpios(pinfo); pinfo->prepared = false; return 0; } static int boe_panel_prepare(struct drm_panel *panel) { struct panel_info *pinfo = to_panel_info(panel); int err; if (pinfo->prepared) return 0; gpiod_set_value(pinfo->pp18_gpio, 1); /* T1: 5ms - 6ms */ usleep_range(5000, 6000); gpiod_set_value(pinfo->pp33_gpio, 1); /* reset sequence */ /* T2: 14ms - 15ms */ usleep_range(14000, 15000); gpiod_set_value(pinfo->enable_gpio, 1); /* T3: 1ms - 2ms */ usleep_range(1000, 2000); gpiod_set_value(pinfo->enable_gpio, 0); /* T4: 1ms - 2ms */ usleep_range(1000, 2000); gpiod_set_value(pinfo->enable_gpio, 1); /* T5: 5ms - 6ms */ usleep_range(5000, 6000); /* send init code */ err = send_mipi_cmds(panel, pinfo->desc->on_cmds); if (err < 0) { DRM_DEV_ERROR(panel->dev, "failed to send DCS Init Code: %d\n", err); goto poweroff; } err = mipi_dsi_dcs_exit_sleep_mode(pinfo->link); if (err < 0) { DRM_DEV_ERROR(panel->dev, "failed to exit sleep mode: %d\n", err); goto poweroff; } /* T6: 120ms - 121ms */ usleep_range(120000, 121000); err = mipi_dsi_dcs_set_display_on(pinfo->link); if (err < 0) { DRM_DEV_ERROR(panel->dev, "failed to set display on: %d\n", err); goto poweroff; } /* T7: 20ms - 21ms */ usleep_range(20000, 21000); pinfo->prepared = true; return 0; poweroff: disable_gpios(pinfo); return err; } static int boe_panel_enable(struct drm_panel *panel) { struct panel_info *pinfo = to_panel_info(panel); int ret; if (pinfo->enabled) return 0; usleep_range(120000, 121000); ret = mipi_dsi_dcs_set_display_on(pinfo->link); if (ret < 0) { DRM_DEV_ERROR(panel->dev, "failed to set display on: %d\n", ret); return ret; } pinfo->enabled = true; return 0; } static int boe_panel_get_modes(struct drm_panel *panel, struct drm_connector *connector) { struct panel_info *pinfo = to_panel_info(panel); const struct drm_display_mode *m = pinfo->desc->display_mode; struct drm_display_mode *mode; mode = drm_mode_duplicate(connector->dev, m); if (!mode) { DRM_DEV_ERROR(pinfo->base.dev, "failed to add mode %ux%u@%u\n", m->hdisplay, m->vdisplay, m->vrefresh); return -ENOMEM; } drm_mode_set_name(mode); drm_mode_probed_add(connector, mode); connector->display_info.width_mm = pinfo->desc->width_mm; connector->display_info.height_mm = pinfo->desc->height_mm; connector->display_info.bpc = pinfo->desc->bpc; return 1; } static const struct drm_panel_funcs panel_funcs = { .disable = boe_panel_disable, .unprepare = boe_panel_unprepare, .prepare = boe_panel_prepare, .enable = boe_panel_enable, .get_modes = boe_panel_get_modes, }; static const struct drm_display_mode default_display_mode = { .clock = 159420, .hdisplay = 1200, .hsync_start = 1200 + 80, .hsync_end = 1200 + 80 + 60, .htotal = 1200 + 80 + 60 + 24, .vdisplay = 1920, .vsync_start = 1920 + 10, .vsync_end = 1920 + 10 + 14, .vtotal = 1920 + 10 + 14 + 4, .vrefresh = 60, }; /* 8 inch */ static const struct panel_cmd boe_himax8279d8p_on_cmds[] = { { 0xB0, 0x05 }, { 0xB1, 0xE5 }, { 0xB3, 0x52 }, { 0xC0, 0x00 }, { 0xC2, 0x57 }, { 0xD9, 0x85 }, { 0xB0, 0x01 }, { 0xC8, 0x00 }, { 0xC9, 0x00 }, { 0xCC, 0x26 }, { 0xCD, 0x26 }, { 0xDC, 0x00 }, { 0xDD, 0x00 }, { 0xE0, 0x26 }, { 0xE1, 0x26 }, { 0xB0, 0x03 }, { 0xC3, 0x2A }, { 0xE7, 0x2A }, { 0xC5, 0x2A }, { 0xDE, 0x2A }, { 0xBC, 0x02 }, { 0xCB, 0x02 }, { 0xB0, 0x00 }, { 0xB6, 0x03 }, { 0xBA, 0x8B }, { 0xBF, 0x15 }, { 0xC0, 0x18 }, { 0xC2, 0x14 }, { 0xC3, 0x02 }, { 0xC4, 0x14 }, { 0xC5, 0x02 }, { 0xCC, 0x0A }, { 0xB0, 0x06 }, { 0xC0, 0xA5 }, { 0xD5, 0x20 }, { 0xC0, 0x00 }, { 0xB0, 0x02 }, { 0xC0, 0x00 }, { 0xC1, 0x02 }, { 0xC2, 0x06 }, { 0xC3, 0x16 }, { 0xC4, 0x0E }, { 0xC5, 0x18 }, { 0xC6, 0x26 }, { 0xC7, 0x32 }, { 0xC8, 0x3F }, { 0xC9, 0x3F }, { 0xCA, 0x3F }, { 0xCB, 0x3F }, { 0xCC, 0x3D }, { 0xCD, 0x2F }, { 0xCE, 0x2F }, { 0xCF, 0x2F }, { 0xD0, 0x07 }, { 0xD2, 0x00 }, { 0xD3, 0x02 }, { 0xD4, 0x06 }, { 0xD5, 0x12 }, { 0xD6, 0x0A }, { 0xD7, 0x14 }, { 0xD8, 0x22 }, { 0xD9, 0x2E }, { 0xDA, 0x3D }, { 0xDB, 0x3F }, { 0xDC, 0x3F }, { 0xDD, 0x3F }, { 0xDE, 0x3D }, { 0xDF, 0x2F }, { 0xE0, 0x2F }, { 0xE1, 0x2F }, { 0xE2, 0x07 }, { 0xB0, 0x07 }, { 0xB1, 0x18 }, { 0xB2, 0x19 }, { 0xB3, 0x2E }, { 0xB4, 0x52 }, { 0xB5, 0x72 }, { 0xB6, 0x8C }, { 0xB7, 0xBD }, { 0xB8, 0xEB }, { 0xB9, 0x47 }, { 0xBA, 0x96 }, { 0xBB, 0x1E }, { 0xBC, 0x90 }, { 0xBD, 0x93 }, { 0xBE, 0xFA }, { 0xBF, 0x56 }, { 0xC0, 0x8C }, { 0xC1, 0xB7 }, { 0xC2, 0xCC }, { 0xC3, 0xDF }, { 0xC4, 0xE8 }, { 0xC5, 0xF0 }, { 0xC6, 0xF8 }, { 0xC7, 0xFA }, { 0xC8, 0xFC }, { 0xC9, 0x00 }, { 0xCA, 0x00 }, { 0xCB, 0x5A }, { 0xCC, 0xAF }, { 0xCD, 0xFF }, { 0xCE, 0xFF }, { 0xB0, 0x08 }, { 0xB1, 0x04 }, { 0xB2, 0x15 }, { 0xB3, 0x2D }, { 0xB4, 0x51 }, { 0xB5, 0x72 }, { 0xB6, 0x8D }, { 0xB7, 0xBE }, { 0xB8, 0xED }, { 0xB9, 0x4A }, { 0xBA, 0x9A }, { 0xBB, 0x23 }, { 0xBC, 0x95 }, { 0xBD, 0x98 }, { 0xBE, 0xFF }, { 0xBF, 0x59 }, { 0xC0, 0x8E }, { 0xC1, 0xB9 }, { 0xC2, 0xCD }, { 0xC3, 0xDF }, { 0xC4, 0xE8 }, { 0xC5, 0xF0 }, { 0xC6, 0xF8 }, { 0xC7, 0xFA }, { 0xC8, 0xFC }, { 0xC9, 0x00 }, { 0xCA, 0x00 }, { 0xCB, 0x5A }, { 0xCC, 0xAF }, { 0xCD, 0xFF }, { 0xCE, 0xFF }, { 0xB0, 0x09 }, { 0xB1, 0x04 }, { 0xB2, 0x2C }, { 0xB3, 0x36 }, { 0xB4, 0x53 }, { 0xB5, 0x73 }, { 0xB6, 0x8E }, { 0xB7, 0xC0 }, { 0xB8, 0xEF }, { 0xB9, 0x4C }, { 0xBA, 0x9D }, { 0xBB, 0x25 }, { 0xBC, 0x96 }, { 0xBD, 0x9A }, { 0xBE, 0x01 }, { 0xBF, 0x59 }, { 0xC0, 0x8E }, { 0xC1, 0xB9 }, { 0xC2, 0xCD }, { 0xC3, 0xDF }, { 0xC4, 0xE8 }, { 0xC5, 0xF0 }, { 0xC6, 0xF8 }, { 0xC7, 0xFA }, { 0xC8, 0xFC }, { 0xC9, 0x00 }, { 0xCA, 0x00 }, { 0xCB, 0x5A }, { 0xCC, 0xBF }, { 0xCD, 0xFF }, { 0xCE, 0xFF }, { 0xB0, 0x0A }, { 0xB1, 0x18 }, { 0xB2, 0x19 }, { 0xB3, 0x2E }, { 0xB4, 0x52 }, { 0xB5, 0x72 }, { 0xB6, 0x8C }, { 0xB7, 0xBD }, { 0xB8, 0xEB }, { 0xB9, 0x47 }, { 0xBA, 0x96 }, { 0xBB, 0x1E }, { 0xBC, 0x90 }, { 0xBD, 0x93 }, { 0xBE, 0xFA }, { 0xBF, 0x56 }, { 0xC0, 0x8C }, { 0xC1, 0xB7 }, { 0xC2, 0xCC }, { 0xC3, 0xDF }, { 0xC4, 0xE8 }, { 0xC5, 0xF0 }, { 0xC6, 0xF8 }, { 0xC7, 0xFA }, { 0xC8, 0xFC }, { 0xC9, 0x00 }, { 0xCA, 0x00 }, { 0xCB, 0x5A }, { 0xCC, 0xAF }, { 0xCD, 0xFF }, { 0xCE, 0xFF }, { 0xB0, 0x0B }, { 0xB1, 0x04 }, { 0xB2, 0x15 }, { 0xB3, 0x2D }, { 0xB4, 0x51 }, { 0xB5, 0x72 }, { 0xB6, 0x8D }, { 0xB7, 0xBE }, { 0xB8, 0xED }, { 0xB9, 0x4A }, { 0xBA, 0x9A }, { 0xBB, 0x23 }, { 0xBC, 0x95 }, { 0xBD, 0x98 }, { 0xBE, 0xFF }, { 0xBF, 0x59 }, { 0xC0, 0x8E }, { 0xC1, 0xB9 }, { 0xC2, 0xCD }, { 0xC3, 0xDF }, { 0xC4, 0xE8 }, { 0xC5, 0xF0 }, { 0xC6, 0xF8 }, { 0xC7, 0xFA }, { 0xC8, 0xFC }, { 0xC9, 0x00 }, { 0xCA, 0x00 }, { 0xCB, 0x5A }, { 0xCC, 0xAF }, { 0xCD, 0xFF }, { 0xCE, 0xFF }, { 0xB0, 0x0C }, { 0xB1, 0x04 }, { 0xB2, 0x2C }, { 0xB3, 0x36 }, { 0xB4, 0x53 }, { 0xB5, 0x73 }, { 0xB6, 0x8E }, { 0xB7, 0xC0 }, { 0xB8, 0xEF }, { 0xB9, 0x4C }, { 0xBA, 0x9D }, { 0xBB, 0x25 }, { 0xBC, 0x96 }, { 0xBD, 0x9A }, { 0xBE, 0x01 }, { 0xBF, 0x59 }, { 0xC0, 0x8E }, { 0xC1, 0xB9 }, { 0xC2, 0xCD }, { 0xC3, 0xDF }, { 0xC4, 0xE8 }, { 0xC5, 0xF0 }, { 0xC6, 0xF8 }, { 0xC7, 0xFA }, { 0xC8, 0xFC }, { 0xC9, 0x00 }, { 0xCA, 0x00 }, { 0xCB, 0x5A }, { 0xCC, 0xBF }, { 0xCD, 0xFF }, { 0xCE, 0xFF }, { 0xB0, 0x04 }, { 0xB5, 0x02 }, { 0xB6, 0x01 }, }; static const struct panel_desc boe_himax8279d8p_panel_desc = { .display_mode = &default_display_mode, .bpc = 8, .width_mm = 107, .height_mm = 172, .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM, .format = MIPI_DSI_FMT_RGB888, .lanes = 4, .on_cmds = boe_himax8279d8p_on_cmds, .on_cmds_num = 260, }; /* 10 inch */ static const struct panel_cmd boe_himax8279d10p_on_cmds[] = { { 0xB0, 0x05 }, { 0xB1, 0xE5 }, { 0xB3, 0x52 }, { 0xB0, 0x00 }, { 0xB6, 0x03 }, { 0xBA, 0x8B }, { 0xBF, 0x1A }, { 0xC0, 0x0F }, { 0xC2, 0x0C }, { 0xC3, 0x02 }, { 0xC4, 0x0C }, { 0xC5, 0x02 }, { 0xB0, 0x01 }, { 0xE0, 0x26 }, { 0xE1, 0x26 }, { 0xDC, 0x00 }, { 0xDD, 0x00 }, { 0xCC, 0x26 }, { 0xCD, 0x26 }, { 0xC8, 0x00 }, { 0xC9, 0x00 }, { 0xD2, 0x03 }, { 0xD3, 0x03 }, { 0xE6, 0x04 }, { 0xE7, 0x04 }, { 0xC4, 0x09 }, { 0xC5, 0x09 }, { 0xD8, 0x0A }, { 0xD9, 0x0A }, { 0xC2, 0x0B }, { 0xC3, 0x0B }, { 0xD6, 0x0C }, { 0xD7, 0x0C }, { 0xC0, 0x05 }, { 0xC1, 0x05 }, { 0xD4, 0x06 }, { 0xD5, 0x06 }, { 0xCA, 0x07 }, { 0xCB, 0x07 }, { 0xDE, 0x08 }, { 0xDF, 0x08 }, { 0xB0, 0x02 }, { 0xC0, 0x00 }, { 0xC1, 0x0D }, { 0xC2, 0x17 }, { 0xC3, 0x26 }, { 0xC4, 0x31 }, { 0xC5, 0x1C }, { 0xC6, 0x2C }, { 0xC7, 0x33 }, { 0xC8, 0x31 }, { 0xC9, 0x37 }, { 0xCA, 0x37 }, { 0xCB, 0x37 }, { 0xCC, 0x39 }, { 0xCD, 0x2E }, { 0xCE, 0x2F }, { 0xCF, 0x2F }, { 0xD0, 0x07 }, { 0xD2, 0x00 }, { 0xD3, 0x0D }, { 0xD4, 0x17 }, { 0xD5, 0x26 }, { 0xD6, 0x31 }, { 0xD7, 0x3F }, { 0xD8, 0x3F }, { 0xD9, 0x3F }, { 0xDA, 0x3F }, { 0xDB, 0x37 }, { 0xDC, 0x37 }, { 0xDD, 0x37 }, { 0xDE, 0x39 }, { 0xDF, 0x2E }, { 0xE0, 0x2F }, { 0xE1, 0x2F }, { 0xE2, 0x07 }, { 0xB0, 0x03 }, { 0xC8, 0x0B }, { 0xC9, 0x07 }, { 0xC3, 0x00 }, { 0xE7, 0x00 }, { 0xC5, 0x2A }, { 0xDE, 0x2A }, { 0xCA, 0x43 }, { 0xC9, 0x07 }, { 0xE4, 0xC0 }, { 0xE5, 0x0D }, { 0xCB, 0x01 }, { 0xBC, 0x01 }, { 0xB0, 0x06 }, { 0xB8, 0xA5 }, { 0xC0, 0xA5 }, { 0xC7, 0x0F }, { 0xD5, 0x32 }, { 0xB8, 0x00 }, { 0xC0, 0x00 }, { 0xBC, 0x00 }, { 0xB0, 0x07 }, { 0xB1, 0x00 }, { 0xB2, 0x05 }, { 0xB3, 0x10 }, { 0xB4, 0x22 }, { 0xB5, 0x36 }, { 0xB6, 0x4A }, { 0xB7, 0x6C }, { 0xB8, 0x9A }, { 0xB9, 0xD7 }, { 0xBA, 0x17 }, { 0xBB, 0x92 }, { 0xBC, 0x15 }, { 0xBD, 0x18 }, { 0xBE, 0x8C }, { 0xBF, 0x00 }, { 0xC0, 0x3A }, { 0xC1, 0x72 }, { 0xC2, 0x8C }, { 0xC3, 0xA5 }, { 0xC4, 0xB1 }, { 0xC5, 0xBE }, { 0xC6, 0xCA }, { 0xC7, 0xD1 }, { 0xC8, 0xD4 }, { 0xC9, 0x00 }, { 0xCA, 0x00 }, { 0xCB, 0x16 }, { 0xCC, 0xAF }, { 0xCD, 0xFF }, { 0xCE, 0xFF }, { 0xB0, 0x08 }, { 0xB1, 0x04 }, { 0xB2, 0x05 }, { 0xB3, 0x11 }, { 0xB4, 0x24 }, { 0xB5, 0x39 }, { 0xB6, 0x4E }, { 0xB7, 0x72 }, { 0xB8, 0xA3 }, { 0xB9, 0xE1 }, { 0xBA, 0x25 }, { 0xBB, 0xA8 }, { 0xBC, 0x2E }, { 0xBD, 0x32 }, { 0xBE, 0xAD }, { 0xBF, 0x28 }, { 0xC0, 0x63 }, { 0xC1, 0x9B }, { 0xC2, 0xB5 }, { 0xC3, 0xCF }, { 0xC4, 0xDB }, { 0xC5, 0xE8 }, { 0xC6, 0xF5 }, { 0xC7, 0xFA }, { 0xC8, 0xFC }, { 0xC9, 0x00 }, { 0xCA, 0x00 }, { 0xCB, 0x16 }, { 0xCC, 0xAF }, { 0xCD, 0xFF }, { 0xCE, 0xFF }, { 0xB0, 0x09 }, { 0xB1, 0x04 }, { 0xB2, 0x04 }, { 0xB3, 0x0F }, { 0xB4, 0x22 }, { 0xB5, 0x37 }, { 0xB6, 0x4D }, { 0xB7, 0x71 }, { 0xB8, 0xA2 }, { 0xB9, 0xE1 }, { 0xBA, 0x26 }, { 0xBB, 0xA9 }, { 0xBC, 0x2F }, { 0xBD, 0x33 }, { 0xBE, 0xAC }, { 0xBF, 0x24 }, { 0xC0, 0x5D }, { 0xC1, 0x94 }, { 0xC2, 0xAC }, { 0xC3, 0xC5 }, { 0xC4, 0xD1 }, { 0xC5, 0xDC }, { 0xC6, 0xE8 }, { 0xC7, 0xED }, { 0xC8, 0xF0 }, { 0xC9, 0x00 }, { 0xCA, 0x00 }, { 0xCB, 0x16 }, { 0xCC, 0xAF }, { 0xCD, 0xFF }, { 0xCE, 0xFF }, { 0xB0, 0x0A }, { 0xB1, 0x00 }, { 0xB2, 0x05 }, { 0xB3, 0x10 }, { 0xB4, 0x22 }, { 0xB5, 0x36 }, { 0xB6, 0x4A }, { 0xB7, 0x6C }, { 0xB8, 0x9A }, { 0xB9, 0xD7 }, { 0xBA, 0x17 }, { 0xBB, 0x92 }, { 0xBC, 0x15 }, { 0xBD, 0x18 }, { 0xBE, 0x8C }, { 0xBF, 0x00 }, { 0xC0, 0x3A }, { 0xC1, 0x72 }, { 0xC2, 0x8C }, { 0xC3, 0xA5 }, { 0xC4, 0xB1 }, { 0xC5, 0xBE }, { 0xC6, 0xCA }, { 0xC7, 0xD1 }, { 0xC8, 0xD4 }, { 0xC9, 0x00 }, { 0xCA, 0x00 }, { 0xCB, 0x16 }, { 0xCC, 0xAF }, { 0xCD, 0xFF }, { 0xCE, 0xFF }, { 0xB0, 0x0B }, { 0xB1, 0x04 }, { 0xB2, 0x05 }, { 0xB3, 0x11 }, { 0xB4, 0x24 }, { 0xB5, 0x39 }, { 0xB6, 0x4E }, { 0xB7, 0x72 }, { 0xB8, 0xA3 }, { 0xB9, 0xE1 }, { 0xBA, 0x25 }, { 0xBB, 0xA8 }, { 0xBC, 0x2E }, { 0xBD, 0x32 }, { 0xBE, 0xAD }, { 0xBF, 0x28 }, { 0xC0, 0x63 }, { 0xC1, 0x9B }, { 0xC2, 0xB5 }, { 0xC3, 0xCF }, { 0xC4, 0xDB }, { 0xC5, 0xE8 }, { 0xC6, 0xF5 }, { 0xC7, 0xFA }, { 0xC8, 0xFC }, { 0xC9, 0x00 }, { 0xCA, 0x00 }, { 0xCB, 0x16 }, { 0xCC, 0xAF }, { 0xCD, 0xFF }, { 0xCE, 0xFF }, { 0xB0, 0x0C }, { 0xB1, 0x04 }, { 0xB2, 0x04 }, { 0xB3, 0x0F }, { 0xB4, 0x22 }, { 0xB5, 0x37 }, { 0xB6, 0x4D }, { 0xB7, 0x71 }, { 0xB8, 0xA2 }, { 0xB9, 0xE1 }, { 0xBA, 0x26 }, { 0xBB, 0xA9 }, { 0xBC, 0x2F }, { 0xBD, 0x33 }, { 0xBE, 0xAC }, { 0xBF, 0x24 }, { 0xC0, 0x5D }, { 0xC1, 0x94 }, { 0xC2, 0xAC }, { 0xC3, 0xC5 }, { 0xC4, 0xD1 }, { 0xC5, 0xDC }, { 0xC6, 0xE8 }, { 0xC7, 0xED }, { 0xC8, 0xF0 }, { 0xC9, 0x00 }, { 0xCA, 0x00 }, { 0xCB, 0x16 }, { 0xCC, 0xAF }, { 0xCD, 0xFF }, { 0xCE, 0xFF }, }; static const struct panel_desc boe_himax8279d10p_panel_desc = { .display_mode = &default_display_mode, .bpc = 8, .width_mm = 135, .height_mm = 216, .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM, .format = MIPI_DSI_FMT_RGB888, .lanes = 4, .on_cmds = boe_himax8279d10p_on_cmds, .on_cmds_num = 283, }; static const struct of_device_id panel_of_match[] = { { .compatible = "boe,himax8279d8p", .data = &boe_himax8279d8p_panel_desc, }, { .compatible = "boe,himax8279d10p", .data = &boe_himax8279d10p_panel_desc, }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, panel_of_match); static int panel_add(struct panel_info *pinfo) { struct device *dev = &pinfo->link->dev; int ret; pinfo->pp18_gpio = devm_gpiod_get(dev, "pp18", GPIOD_OUT_HIGH); if (IS_ERR(pinfo->pp18_gpio)) { ret = PTR_ERR(pinfo->pp18_gpio); if (ret != -EPROBE_DEFER) DRM_DEV_ERROR(dev, "failed to get pp18 gpio: %d\n", ret); return ret; } pinfo->pp33_gpio = devm_gpiod_get(dev, "pp33", GPIOD_OUT_HIGH); if (IS_ERR(pinfo->pp33_gpio)) { ret = PTR_ERR(pinfo->pp33_gpio); if (ret != -EPROBE_DEFER) DRM_DEV_ERROR(dev, "failed to get pp33 gpio: %d\n", ret); return ret; } pinfo->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH); if (IS_ERR(pinfo->enable_gpio)) { ret = PTR_ERR(pinfo->enable_gpio); if (ret != -EPROBE_DEFER) DRM_DEV_ERROR(dev, "failed to get enable gpio: %d\n", ret); return ret; } drm_panel_init(&pinfo->base, dev, &panel_funcs, DRM_MODE_CONNECTOR_DSI); ret = drm_panel_of_backlight(&pinfo->base); if (ret) return ret; return drm_panel_add(&pinfo->base); } static int panel_probe(struct mipi_dsi_device *dsi) { struct panel_info *pinfo; const struct panel_desc *desc; int err; pinfo = devm_kzalloc(&dsi->dev, sizeof(*pinfo), GFP_KERNEL); if (!pinfo) return -ENOMEM; desc = of_device_get_match_data(&dsi->dev); dsi->mode_flags = desc->mode_flags; dsi->format = desc->format; dsi->lanes = desc->lanes; pinfo->desc = desc; pinfo->link = dsi; mipi_dsi_set_drvdata(dsi, pinfo); err = panel_add(pinfo); if (err < 0) return err; err = mipi_dsi_attach(dsi); if (err < 0) drm_panel_remove(&pinfo->base); return err; } static int panel_remove(struct mipi_dsi_device *dsi) { struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi); int err; err = boe_panel_disable(&pinfo->base); if (err < 0) DRM_DEV_ERROR(&dsi->dev, "failed to disable panel: %d\n", err); err = boe_panel_unprepare(&pinfo->base); if (err < 0) DRM_DEV_ERROR(&dsi->dev, "failed to unprepare panel: %d\n", err); err = mipi_dsi_detach(dsi); if (err < 0) DRM_DEV_ERROR(&dsi->dev, "failed to detach from DSI host: %d\n", err); drm_panel_remove(&pinfo->base); return 0; } static void panel_shutdown(struct mipi_dsi_device *dsi) { struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi); boe_panel_disable(&pinfo->base); boe_panel_unprepare(&pinfo->base); } static struct mipi_dsi_driver panel_driver = { .driver = { .name = "panel-boe-himax8279d", .of_match_table = panel_of_match, }, .probe = panel_probe, .remove = panel_remove, .shutdown = panel_shutdown, }; module_mipi_dsi_driver(panel_driver); MODULE_AUTHOR("Jerry Han <jerry.han.hq@gmail.com>"); MODULE_DESCRIPTION("Boe Himax8279d driver"); MODULE_LICENSE("GPL v2");
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with Cregit http://github.com/cregit/cregit
Version 2.0-RC1