Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Raydium RM67191 MIPI-DSI panel driver
0004  *
0005  * Copyright 2019 NXP
0006  */
0007 
0008 #include <linux/backlight.h>
0009 #include <linux/delay.h>
0010 #include <linux/gpio/consumer.h>
0011 #include <linux/media-bus-format.h>
0012 #include <linux/module.h>
0013 #include <linux/of.h>
0014 #include <linux/regulator/consumer.h>
0015 
0016 #include <video/mipi_display.h>
0017 #include <video/of_videomode.h>
0018 #include <video/videomode.h>
0019 
0020 #include <drm/drm_crtc.h>
0021 #include <drm/drm_mipi_dsi.h>
0022 #include <drm/drm_panel.h>
0023 
0024 /* Panel specific color-format bits */
0025 #define COL_FMT_16BPP 0x55
0026 #define COL_FMT_18BPP 0x66
0027 #define COL_FMT_24BPP 0x77
0028 
0029 /* Write Manufacture Command Set Control */
0030 #define WRMAUCCTR 0xFE
0031 
0032 /* Manufacturer Command Set pages (CMD2) */
0033 struct cmd_set_entry {
0034     u8 cmd;
0035     u8 param;
0036 };
0037 
0038 /*
0039  * There is no description in the Reference Manual about these commands.
0040  * We received them from vendor, so just use them as is.
0041  */
0042 static const struct cmd_set_entry manufacturer_cmd_set[] = {
0043     {0xFE, 0x0B},
0044     {0x28, 0x40},
0045     {0x29, 0x4F},
0046     {0xFE, 0x0E},
0047     {0x4B, 0x00},
0048     {0x4C, 0x0F},
0049     {0x4D, 0x20},
0050     {0x4E, 0x40},
0051     {0x4F, 0x60},
0052     {0x50, 0xA0},
0053     {0x51, 0xC0},
0054     {0x52, 0xE0},
0055     {0x53, 0xFF},
0056     {0xFE, 0x0D},
0057     {0x18, 0x08},
0058     {0x42, 0x00},
0059     {0x08, 0x41},
0060     {0x46, 0x02},
0061     {0x72, 0x09},
0062     {0xFE, 0x0A},
0063     {0x24, 0x17},
0064     {0x04, 0x07},
0065     {0x1A, 0x0C},
0066     {0x0F, 0x44},
0067     {0xFE, 0x04},
0068     {0x00, 0x0C},
0069     {0x05, 0x08},
0070     {0x06, 0x08},
0071     {0x08, 0x08},
0072     {0x09, 0x08},
0073     {0x0A, 0xE6},
0074     {0x0B, 0x8C},
0075     {0x1A, 0x12},
0076     {0x1E, 0xE0},
0077     {0x29, 0x93},
0078     {0x2A, 0x93},
0079     {0x2F, 0x02},
0080     {0x31, 0x02},
0081     {0x33, 0x05},
0082     {0x37, 0x2D},
0083     {0x38, 0x2D},
0084     {0x3A, 0x1E},
0085     {0x3B, 0x1E},
0086     {0x3D, 0x27},
0087     {0x3F, 0x80},
0088     {0x40, 0x40},
0089     {0x41, 0xE0},
0090     {0x4F, 0x2F},
0091     {0x50, 0x1E},
0092     {0xFE, 0x06},
0093     {0x00, 0xCC},
0094     {0x05, 0x05},
0095     {0x07, 0xA2},
0096     {0x08, 0xCC},
0097     {0x0D, 0x03},
0098     {0x0F, 0xA2},
0099     {0x32, 0xCC},
0100     {0x37, 0x05},
0101     {0x39, 0x83},
0102     {0x3A, 0xCC},
0103     {0x41, 0x04},
0104     {0x43, 0x83},
0105     {0x44, 0xCC},
0106     {0x49, 0x05},
0107     {0x4B, 0xA2},
0108     {0x4C, 0xCC},
0109     {0x51, 0x03},
0110     {0x53, 0xA2},
0111     {0x75, 0xCC},
0112     {0x7A, 0x03},
0113     {0x7C, 0x83},
0114     {0x7D, 0xCC},
0115     {0x82, 0x02},
0116     {0x84, 0x83},
0117     {0x85, 0xEC},
0118     {0x86, 0x0F},
0119     {0x87, 0xFF},
0120     {0x88, 0x00},
0121     {0x8A, 0x02},
0122     {0x8C, 0xA2},
0123     {0x8D, 0xEA},
0124     {0x8E, 0x01},
0125     {0x8F, 0xE8},
0126     {0xFE, 0x06},
0127     {0x90, 0x0A},
0128     {0x92, 0x06},
0129     {0x93, 0xA0},
0130     {0x94, 0xA8},
0131     {0x95, 0xEC},
0132     {0x96, 0x0F},
0133     {0x97, 0xFF},
0134     {0x98, 0x00},
0135     {0x9A, 0x02},
0136     {0x9C, 0xA2},
0137     {0xAC, 0x04},
0138     {0xFE, 0x06},
0139     {0xB1, 0x12},
0140     {0xB2, 0x17},
0141     {0xB3, 0x17},
0142     {0xB4, 0x17},
0143     {0xB5, 0x17},
0144     {0xB6, 0x11},
0145     {0xB7, 0x08},
0146     {0xB8, 0x09},
0147     {0xB9, 0x06},
0148     {0xBA, 0x07},
0149     {0xBB, 0x17},
0150     {0xBC, 0x17},
0151     {0xBD, 0x17},
0152     {0xBE, 0x17},
0153     {0xBF, 0x17},
0154     {0xC0, 0x17},
0155     {0xC1, 0x17},
0156     {0xC2, 0x17},
0157     {0xC3, 0x17},
0158     {0xC4, 0x0F},
0159     {0xC5, 0x0E},
0160     {0xC6, 0x00},
0161     {0xC7, 0x01},
0162     {0xC8, 0x10},
0163     {0xFE, 0x06},
0164     {0x95, 0xEC},
0165     {0x8D, 0xEE},
0166     {0x44, 0xEC},
0167     {0x4C, 0xEC},
0168     {0x32, 0xEC},
0169     {0x3A, 0xEC},
0170     {0x7D, 0xEC},
0171     {0x75, 0xEC},
0172     {0x00, 0xEC},
0173     {0x08, 0xEC},
0174     {0x85, 0xEC},
0175     {0xA6, 0x21},
0176     {0xA7, 0x05},
0177     {0xA9, 0x06},
0178     {0x82, 0x06},
0179     {0x41, 0x06},
0180     {0x7A, 0x07},
0181     {0x37, 0x07},
0182     {0x05, 0x06},
0183     {0x49, 0x06},
0184     {0x0D, 0x04},
0185     {0x51, 0x04},
0186 };
0187 
0188 static const u32 rad_bus_formats[] = {
0189     MEDIA_BUS_FMT_RGB888_1X24,
0190     MEDIA_BUS_FMT_RGB666_1X18,
0191     MEDIA_BUS_FMT_RGB565_1X16,
0192 };
0193 
0194 static const u32 rad_bus_flags = DRM_BUS_FLAG_DE_LOW |
0195                  DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE;
0196 
0197 struct rad_panel {
0198     struct drm_panel panel;
0199     struct mipi_dsi_device *dsi;
0200 
0201     struct gpio_desc *reset;
0202     struct backlight_device *backlight;
0203 
0204     struct regulator_bulk_data *supplies;
0205     unsigned int num_supplies;
0206 
0207     bool prepared;
0208     bool enabled;
0209 };
0210 
0211 static const struct drm_display_mode default_mode = {
0212     .clock = 132000,
0213     .hdisplay = 1080,
0214     .hsync_start = 1080 + 20,
0215     .hsync_end = 1080 + 20 + 2,
0216     .htotal = 1080 + 20 + 2 + 34,
0217     .vdisplay = 1920,
0218     .vsync_start = 1920 + 10,
0219     .vsync_end = 1920 + 10 + 2,
0220     .vtotal = 1920 + 10 + 2 + 4,
0221     .width_mm = 68,
0222     .height_mm = 121,
0223     .flags = DRM_MODE_FLAG_NHSYNC |
0224          DRM_MODE_FLAG_NVSYNC,
0225 };
0226 
0227 static inline struct rad_panel *to_rad_panel(struct drm_panel *panel)
0228 {
0229     return container_of(panel, struct rad_panel, panel);
0230 }
0231 
0232 static int rad_panel_push_cmd_list(struct mipi_dsi_device *dsi)
0233 {
0234     size_t i;
0235     size_t count = ARRAY_SIZE(manufacturer_cmd_set);
0236     int ret = 0;
0237 
0238     for (i = 0; i < count; i++) {
0239         const struct cmd_set_entry *entry = &manufacturer_cmd_set[i];
0240         u8 buffer[2] = { entry->cmd, entry->param };
0241 
0242         ret = mipi_dsi_generic_write(dsi, &buffer, sizeof(buffer));
0243         if (ret < 0)
0244             return ret;
0245     }
0246 
0247     return ret;
0248 };
0249 
0250 static int color_format_from_dsi_format(enum mipi_dsi_pixel_format format)
0251 {
0252     switch (format) {
0253     case MIPI_DSI_FMT_RGB565:
0254         return COL_FMT_16BPP;
0255     case MIPI_DSI_FMT_RGB666:
0256     case MIPI_DSI_FMT_RGB666_PACKED:
0257         return COL_FMT_18BPP;
0258     case MIPI_DSI_FMT_RGB888:
0259         return COL_FMT_24BPP;
0260     default:
0261         return COL_FMT_24BPP; /* for backward compatibility */
0262     }
0263 };
0264 
0265 static int rad_panel_prepare(struct drm_panel *panel)
0266 {
0267     struct rad_panel *rad = to_rad_panel(panel);
0268     int ret;
0269 
0270     if (rad->prepared)
0271         return 0;
0272 
0273     ret = regulator_bulk_enable(rad->num_supplies, rad->supplies);
0274     if (ret)
0275         return ret;
0276 
0277     if (rad->reset) {
0278         gpiod_set_value_cansleep(rad->reset, 1);
0279         usleep_range(3000, 5000);
0280         gpiod_set_value_cansleep(rad->reset, 0);
0281         usleep_range(18000, 20000);
0282     }
0283 
0284     rad->prepared = true;
0285 
0286     return 0;
0287 }
0288 
0289 static int rad_panel_unprepare(struct drm_panel *panel)
0290 {
0291     struct rad_panel *rad = to_rad_panel(panel);
0292     int ret;
0293 
0294     if (!rad->prepared)
0295         return 0;
0296 
0297     /*
0298      * Right after asserting the reset, we need to release it, so that the
0299      * touch driver can have an active connection with the touch controller
0300      * even after the display is turned off.
0301      */
0302     if (rad->reset) {
0303         gpiod_set_value_cansleep(rad->reset, 1);
0304         usleep_range(15000, 17000);
0305         gpiod_set_value_cansleep(rad->reset, 0);
0306     }
0307 
0308     ret = regulator_bulk_disable(rad->num_supplies, rad->supplies);
0309     if (ret)
0310         return ret;
0311 
0312     rad->prepared = false;
0313 
0314     return 0;
0315 }
0316 
0317 static int rad_panel_enable(struct drm_panel *panel)
0318 {
0319     struct rad_panel *rad = to_rad_panel(panel);
0320     struct mipi_dsi_device *dsi = rad->dsi;
0321     struct device *dev = &dsi->dev;
0322     int color_format = color_format_from_dsi_format(dsi->format);
0323     int ret;
0324 
0325     if (rad->enabled)
0326         return 0;
0327 
0328     dsi->mode_flags |= MIPI_DSI_MODE_LPM;
0329 
0330     ret = rad_panel_push_cmd_list(dsi);
0331     if (ret < 0) {
0332         dev_err(dev, "Failed to send MCS (%d)\n", ret);
0333         goto fail;
0334     }
0335 
0336     /* Select User Command Set table (CMD1) */
0337     ret = mipi_dsi_generic_write(dsi, (u8[]){ WRMAUCCTR, 0x00 }, 2);
0338     if (ret < 0)
0339         goto fail;
0340 
0341     /* Software reset */
0342     ret = mipi_dsi_dcs_soft_reset(dsi);
0343     if (ret < 0) {
0344         dev_err(dev, "Failed to do Software Reset (%d)\n", ret);
0345         goto fail;
0346     }
0347 
0348     usleep_range(15000, 17000);
0349 
0350     /* Set DSI mode */
0351     ret = mipi_dsi_generic_write(dsi, (u8[]){ 0xC2, 0x0B }, 2);
0352     if (ret < 0) {
0353         dev_err(dev, "Failed to set DSI mode (%d)\n", ret);
0354         goto fail;
0355     }
0356     /* Set tear ON */
0357     ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
0358     if (ret < 0) {
0359         dev_err(dev, "Failed to set tear ON (%d)\n", ret);
0360         goto fail;
0361     }
0362     /* Set tear scanline */
0363     ret = mipi_dsi_dcs_set_tear_scanline(dsi, 0x380);
0364     if (ret < 0) {
0365         dev_err(dev, "Failed to set tear scanline (%d)\n", ret);
0366         goto fail;
0367     }
0368     /* Set pixel format */
0369     ret = mipi_dsi_dcs_set_pixel_format(dsi, color_format);
0370     dev_dbg(dev, "Interface color format set to 0x%x\n", color_format);
0371     if (ret < 0) {
0372         dev_err(dev, "Failed to set pixel format (%d)\n", ret);
0373         goto fail;
0374     }
0375     /* Exit sleep mode */
0376     ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
0377     if (ret < 0) {
0378         dev_err(dev, "Failed to exit sleep mode (%d)\n", ret);
0379         goto fail;
0380     }
0381 
0382     usleep_range(5000, 7000);
0383 
0384     ret = mipi_dsi_dcs_set_display_on(dsi);
0385     if (ret < 0) {
0386         dev_err(dev, "Failed to set display ON (%d)\n", ret);
0387         goto fail;
0388     }
0389 
0390     backlight_enable(rad->backlight);
0391 
0392     rad->enabled = true;
0393 
0394     return 0;
0395 
0396 fail:
0397     gpiod_set_value_cansleep(rad->reset, 1);
0398 
0399     return ret;
0400 }
0401 
0402 static int rad_panel_disable(struct drm_panel *panel)
0403 {
0404     struct rad_panel *rad = to_rad_panel(panel);
0405     struct mipi_dsi_device *dsi = rad->dsi;
0406     struct device *dev = &dsi->dev;
0407     int ret;
0408 
0409     if (!rad->enabled)
0410         return 0;
0411 
0412     dsi->mode_flags |= MIPI_DSI_MODE_LPM;
0413 
0414     backlight_disable(rad->backlight);
0415 
0416     usleep_range(10000, 12000);
0417 
0418     ret = mipi_dsi_dcs_set_display_off(dsi);
0419     if (ret < 0) {
0420         dev_err(dev, "Failed to set display OFF (%d)\n", ret);
0421         return ret;
0422     }
0423 
0424     usleep_range(5000, 10000);
0425 
0426     ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
0427     if (ret < 0) {
0428         dev_err(dev, "Failed to enter sleep mode (%d)\n", ret);
0429         return ret;
0430     }
0431 
0432     rad->enabled = false;
0433 
0434     return 0;
0435 }
0436 
0437 static int rad_panel_get_modes(struct drm_panel *panel,
0438                    struct drm_connector *connector)
0439 {
0440     struct drm_display_mode *mode;
0441 
0442     mode = drm_mode_duplicate(connector->dev, &default_mode);
0443     if (!mode) {
0444         dev_err(panel->dev, "failed to add mode %ux%u@%u\n",
0445             default_mode.hdisplay, default_mode.vdisplay,
0446             drm_mode_vrefresh(&default_mode));
0447         return -ENOMEM;
0448     }
0449 
0450     drm_mode_set_name(mode);
0451     mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
0452     drm_mode_probed_add(connector, mode);
0453 
0454     connector->display_info.width_mm = mode->width_mm;
0455     connector->display_info.height_mm = mode->height_mm;
0456     connector->display_info.bus_flags = rad_bus_flags;
0457 
0458     drm_display_info_set_bus_formats(&connector->display_info,
0459                      rad_bus_formats,
0460                      ARRAY_SIZE(rad_bus_formats));
0461     return 1;
0462 }
0463 
0464 static int rad_bl_get_brightness(struct backlight_device *bl)
0465 {
0466     struct mipi_dsi_device *dsi = bl_get_data(bl);
0467     struct rad_panel *rad = mipi_dsi_get_drvdata(dsi);
0468     u16 brightness;
0469     int ret;
0470 
0471     if (!rad->prepared)
0472         return 0;
0473 
0474     dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
0475 
0476     ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
0477     if (ret < 0)
0478         return ret;
0479 
0480     bl->props.brightness = brightness;
0481 
0482     return brightness & 0xff;
0483 }
0484 
0485 static int rad_bl_update_status(struct backlight_device *bl)
0486 {
0487     struct mipi_dsi_device *dsi = bl_get_data(bl);
0488     struct rad_panel *rad = mipi_dsi_get_drvdata(dsi);
0489     int ret = 0;
0490 
0491     if (!rad->prepared)
0492         return 0;
0493 
0494     dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
0495 
0496     ret = mipi_dsi_dcs_set_display_brightness(dsi, bl->props.brightness);
0497     if (ret < 0)
0498         return ret;
0499 
0500     return 0;
0501 }
0502 
0503 static const struct backlight_ops rad_bl_ops = {
0504     .update_status = rad_bl_update_status,
0505     .get_brightness = rad_bl_get_brightness,
0506 };
0507 
0508 static const struct drm_panel_funcs rad_panel_funcs = {
0509     .prepare = rad_panel_prepare,
0510     .unprepare = rad_panel_unprepare,
0511     .enable = rad_panel_enable,
0512     .disable = rad_panel_disable,
0513     .get_modes = rad_panel_get_modes,
0514 };
0515 
0516 static const char * const rad_supply_names[] = {
0517     "v3p3",
0518     "v1p8",
0519 };
0520 
0521 static int rad_init_regulators(struct rad_panel *rad)
0522 {
0523     struct device *dev = &rad->dsi->dev;
0524     int i;
0525 
0526     rad->num_supplies = ARRAY_SIZE(rad_supply_names);
0527     rad->supplies = devm_kcalloc(dev, rad->num_supplies,
0528                      sizeof(*rad->supplies), GFP_KERNEL);
0529     if (!rad->supplies)
0530         return -ENOMEM;
0531 
0532     for (i = 0; i < rad->num_supplies; i++)
0533         rad->supplies[i].supply = rad_supply_names[i];
0534 
0535     return devm_regulator_bulk_get(dev, rad->num_supplies, rad->supplies);
0536 };
0537 
0538 static int rad_panel_probe(struct mipi_dsi_device *dsi)
0539 {
0540     struct device *dev = &dsi->dev;
0541     struct device_node *np = dev->of_node;
0542     struct rad_panel *panel;
0543     struct backlight_properties bl_props;
0544     int ret;
0545     u32 video_mode;
0546 
0547     panel = devm_kzalloc(&dsi->dev, sizeof(*panel), GFP_KERNEL);
0548     if (!panel)
0549         return -ENOMEM;
0550 
0551     mipi_dsi_set_drvdata(dsi, panel);
0552 
0553     panel->dsi = dsi;
0554 
0555     dsi->format = MIPI_DSI_FMT_RGB888;
0556     dsi->mode_flags =  MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO;
0557 
0558     ret = of_property_read_u32(np, "video-mode", &video_mode);
0559     if (!ret) {
0560         switch (video_mode) {
0561         case 0:
0562             /* burst mode */
0563             dsi->mode_flags |= MIPI_DSI_MODE_VIDEO_BURST;
0564             break;
0565         case 1:
0566             /* non-burst mode with sync event */
0567             break;
0568         case 2:
0569             /* non-burst mode with sync pulse */
0570             dsi->mode_flags |= MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
0571             break;
0572         default:
0573             dev_warn(dev, "invalid video mode %d\n", video_mode);
0574             break;
0575         }
0576     }
0577 
0578     ret = of_property_read_u32(np, "dsi-lanes", &dsi->lanes);
0579     if (ret) {
0580         dev_err(dev, "Failed to get dsi-lanes property (%d)\n", ret);
0581         return ret;
0582     }
0583 
0584     panel->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
0585     if (IS_ERR(panel->reset))
0586         return PTR_ERR(panel->reset);
0587 
0588     memset(&bl_props, 0, sizeof(bl_props));
0589     bl_props.type = BACKLIGHT_RAW;
0590     bl_props.brightness = 255;
0591     bl_props.max_brightness = 255;
0592 
0593     panel->backlight = devm_backlight_device_register(dev, dev_name(dev),
0594                               dev, dsi, &rad_bl_ops,
0595                               &bl_props);
0596     if (IS_ERR(panel->backlight)) {
0597         ret = PTR_ERR(panel->backlight);
0598         dev_err(dev, "Failed to register backlight (%d)\n", ret);
0599         return ret;
0600     }
0601 
0602     ret = rad_init_regulators(panel);
0603     if (ret)
0604         return ret;
0605 
0606     drm_panel_init(&panel->panel, dev, &rad_panel_funcs,
0607                DRM_MODE_CONNECTOR_DSI);
0608     dev_set_drvdata(dev, panel);
0609 
0610     drm_panel_add(&panel->panel);
0611 
0612     ret = mipi_dsi_attach(dsi);
0613     if (ret)
0614         drm_panel_remove(&panel->panel);
0615 
0616     return ret;
0617 }
0618 
0619 static int rad_panel_remove(struct mipi_dsi_device *dsi)
0620 {
0621     struct rad_panel *rad = mipi_dsi_get_drvdata(dsi);
0622     struct device *dev = &dsi->dev;
0623     int ret;
0624 
0625     ret = mipi_dsi_detach(dsi);
0626     if (ret)
0627         dev_err(dev, "Failed to detach from host (%d)\n", ret);
0628 
0629     drm_panel_remove(&rad->panel);
0630 
0631     return 0;
0632 }
0633 
0634 static void rad_panel_shutdown(struct mipi_dsi_device *dsi)
0635 {
0636     struct rad_panel *rad = mipi_dsi_get_drvdata(dsi);
0637 
0638     rad_panel_disable(&rad->panel);
0639     rad_panel_unprepare(&rad->panel);
0640 }
0641 
0642 static const struct of_device_id rad_of_match[] = {
0643     { .compatible = "raydium,rm67191", },
0644     { /* sentinel */ }
0645 };
0646 MODULE_DEVICE_TABLE(of, rad_of_match);
0647 
0648 static struct mipi_dsi_driver rad_panel_driver = {
0649     .driver = {
0650         .name = "panel-raydium-rm67191",
0651         .of_match_table = rad_of_match,
0652     },
0653     .probe = rad_panel_probe,
0654     .remove = rad_panel_remove,
0655     .shutdown = rad_panel_shutdown,
0656 };
0657 module_mipi_dsi_driver(rad_panel_driver);
0658 
0659 MODULE_AUTHOR("Robert Chiras <robert.chiras@nxp.com>");
0660 MODULE_DESCRIPTION("DRM Driver for Raydium RM67191 MIPI DSI panel");
0661 MODULE_LICENSE("GPL v2");