0001
0002
0003
0004
0005
0006 #include <linux/clk.h>
0007 #include <linux/module.h>
0008 #include <linux/of_graph.h>
0009 #include <linux/of_platform.h>
0010 #include <linux/of_reserved_mem.h>
0011 #include <linux/mfd/syscon.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/pm_runtime.h>
0014 #include <linux/regmap.h>
0015
0016 #include <drm/drm_atomic_helper.h>
0017 #include <drm/drm_drv.h>
0018 #include <drm/drm_fb_helper.h>
0019 #include <drm/drm_gem_cma_helper.h>
0020 #include <drm/drm_gem_framebuffer_helper.h>
0021 #include <drm/drm_module.h>
0022 #include <drm/drm_probe_helper.h>
0023 #include <drm/drm_vblank.h>
0024
0025 #include "kmb_drv.h"
0026 #include "kmb_dsi.h"
0027 #include "kmb_regs.h"
0028
0029 static int kmb_display_clk_enable(struct kmb_drm_private *kmb)
0030 {
0031 int ret = 0;
0032
0033 ret = clk_prepare_enable(kmb->kmb_clk.clk_lcd);
0034 if (ret) {
0035 drm_err(&kmb->drm, "Failed to enable LCD clock: %d\n", ret);
0036 return ret;
0037 }
0038 DRM_INFO("SUCCESS : enabled LCD clocks\n");
0039 return 0;
0040 }
0041
0042 static int kmb_initialize_clocks(struct kmb_drm_private *kmb, struct device *dev)
0043 {
0044 int ret = 0;
0045 struct regmap *msscam;
0046
0047 kmb->kmb_clk.clk_lcd = devm_clk_get(dev, "clk_lcd");
0048 if (IS_ERR(kmb->kmb_clk.clk_lcd)) {
0049 drm_err(&kmb->drm, "clk_get() failed clk_lcd\n");
0050 return PTR_ERR(kmb->kmb_clk.clk_lcd);
0051 }
0052
0053 kmb->kmb_clk.clk_pll0 = devm_clk_get(dev, "clk_pll0");
0054 if (IS_ERR(kmb->kmb_clk.clk_pll0)) {
0055 drm_err(&kmb->drm, "clk_get() failed clk_pll0 ");
0056 return PTR_ERR(kmb->kmb_clk.clk_pll0);
0057 }
0058 kmb->sys_clk_mhz = clk_get_rate(kmb->kmb_clk.clk_pll0) / 1000000;
0059 drm_info(&kmb->drm, "system clk = %d Mhz", kmb->sys_clk_mhz);
0060
0061 ret = kmb_dsi_clk_init(kmb->kmb_dsi);
0062
0063
0064 clk_set_rate(kmb->kmb_clk.clk_lcd, KMB_LCD_DEFAULT_CLK);
0065 if (clk_get_rate(kmb->kmb_clk.clk_lcd) != KMB_LCD_DEFAULT_CLK) {
0066 drm_err(&kmb->drm, "failed to set to clk_lcd to %d\n",
0067 KMB_LCD_DEFAULT_CLK);
0068 return -1;
0069 }
0070 drm_dbg(&kmb->drm, "clk_lcd = %ld\n", clk_get_rate(kmb->kmb_clk.clk_lcd));
0071
0072 ret = kmb_display_clk_enable(kmb);
0073 if (ret)
0074 return ret;
0075
0076 msscam = syscon_regmap_lookup_by_compatible("intel,keembay-msscam");
0077 if (IS_ERR(msscam)) {
0078 drm_err(&kmb->drm, "failed to get msscam syscon");
0079 return -1;
0080 }
0081
0082
0083 regmap_update_bits(msscam, MSS_CAM_CLK_CTRL, 0x1fff, 0x1fff);
0084 regmap_update_bits(msscam, MSS_CAM_RSTN_CTRL, 0xffffffff, 0xffffffff);
0085 return 0;
0086 }
0087
0088 static void kmb_display_clk_disable(struct kmb_drm_private *kmb)
0089 {
0090 clk_disable_unprepare(kmb->kmb_clk.clk_lcd);
0091 }
0092
0093 static void __iomem *kmb_map_mmio(struct drm_device *drm,
0094 struct platform_device *pdev,
0095 char *name)
0096 {
0097 struct resource *res;
0098 void __iomem *mem;
0099
0100 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
0101 if (!res) {
0102 drm_err(drm, "failed to get resource for %s", name);
0103 return ERR_PTR(-ENOMEM);
0104 }
0105 mem = devm_ioremap_resource(drm->dev, res);
0106 if (IS_ERR(mem))
0107 drm_err(drm, "failed to ioremap %s registers", name);
0108 return mem;
0109 }
0110
0111 static int kmb_hw_init(struct drm_device *drm, unsigned long flags)
0112 {
0113 struct kmb_drm_private *kmb = to_kmb(drm);
0114 struct platform_device *pdev = to_platform_device(drm->dev);
0115 int irq_lcd;
0116 int ret = 0;
0117
0118
0119 kmb->lcd_mmio = kmb_map_mmio(drm, pdev, "lcd");
0120 if (IS_ERR(kmb->lcd_mmio)) {
0121 drm_err(&kmb->drm, "failed to map LCD registers\n");
0122 return -ENOMEM;
0123 }
0124
0125
0126 ret = kmb_dsi_map_mmio(kmb->kmb_dsi);
0127 if (ret)
0128 return ret;
0129
0130
0131 kmb_initialize_clocks(kmb, &pdev->dev);
0132
0133
0134
0135
0136
0137
0138
0139 irq_lcd = platform_get_irq(pdev, 0);
0140 if (irq_lcd < 0) {
0141 ret = irq_lcd;
0142 drm_err(&kmb->drm, "irq_lcd not found");
0143 goto setup_fail;
0144 }
0145
0146
0147 ret = of_reserved_mem_device_init(drm->dev);
0148 if (ret && ret != -ENODEV)
0149 return ret;
0150
0151 spin_lock_init(&kmb->irq_lock);
0152
0153 kmb->irq_lcd = irq_lcd;
0154
0155 return 0;
0156
0157 setup_fail:
0158 of_reserved_mem_device_release(drm->dev);
0159
0160 return ret;
0161 }
0162
0163 static const struct drm_mode_config_funcs kmb_mode_config_funcs = {
0164 .fb_create = drm_gem_fb_create,
0165 .atomic_check = drm_atomic_helper_check,
0166 .atomic_commit = drm_atomic_helper_commit,
0167 };
0168
0169 static int kmb_setup_mode_config(struct drm_device *drm)
0170 {
0171 int ret;
0172 struct kmb_drm_private *kmb = to_kmb(drm);
0173
0174 ret = drmm_mode_config_init(drm);
0175 if (ret)
0176 return ret;
0177 drm->mode_config.min_width = KMB_FB_MIN_WIDTH;
0178 drm->mode_config.min_height = KMB_FB_MIN_HEIGHT;
0179 drm->mode_config.max_width = KMB_FB_MAX_WIDTH;
0180 drm->mode_config.max_height = KMB_FB_MAX_HEIGHT;
0181 drm->mode_config.preferred_depth = 24;
0182 drm->mode_config.funcs = &kmb_mode_config_funcs;
0183
0184 ret = kmb_setup_crtc(drm);
0185 if (ret < 0) {
0186 drm_err(drm, "failed to create crtc\n");
0187 return ret;
0188 }
0189 ret = kmb_dsi_encoder_init(drm, kmb->kmb_dsi);
0190
0191 kmb->crtc.port = of_graph_get_port_by_id(drm->dev->of_node, 0);
0192 ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
0193 if (ret < 0) {
0194 drm_err(drm, "failed to initialize vblank\n");
0195 pm_runtime_disable(drm->dev);
0196 return ret;
0197 }
0198
0199 drm_mode_config_reset(drm);
0200 return 0;
0201 }
0202
0203 static irqreturn_t handle_lcd_irq(struct drm_device *dev)
0204 {
0205 unsigned long status, val, val1;
0206 int plane_id, dma0_state, dma1_state;
0207 struct kmb_drm_private *kmb = to_kmb(dev);
0208 u32 ctrl = 0;
0209
0210 status = kmb_read_lcd(kmb, LCD_INT_STATUS);
0211
0212 spin_lock(&kmb->irq_lock);
0213 if (status & LCD_INT_EOF) {
0214 kmb_write_lcd(kmb, LCD_INT_CLEAR, LCD_INT_EOF);
0215
0216
0217
0218
0219
0220
0221
0222 for (plane_id = LAYER_0;
0223 plane_id < KMB_MAX_PLANES; plane_id++) {
0224 if (kmb->plane_status[plane_id].disable) {
0225 kmb_clr_bitmask_lcd(kmb,
0226 LCD_LAYERn_DMA_CFG
0227 (plane_id),
0228 LCD_DMA_LAYER_ENABLE);
0229
0230 kmb_clr_bitmask_lcd(kmb, LCD_CONTROL,
0231 kmb->plane_status[plane_id].ctrl);
0232
0233 ctrl = kmb_read_lcd(kmb, LCD_CONTROL);
0234 if (!(ctrl & (LCD_CTRL_VL1_ENABLE |
0235 LCD_CTRL_VL2_ENABLE |
0236 LCD_CTRL_GL1_ENABLE |
0237 LCD_CTRL_GL2_ENABLE))) {
0238
0239
0240
0241
0242 kmb_clr_bitmask_lcd(kmb, LCD_CONTROL,
0243 LCD_CTRL_PIPELINE_DMA);
0244 }
0245
0246 kmb->plane_status[plane_id].disable = false;
0247 }
0248 }
0249 if (kmb->kmb_under_flow) {
0250
0251 dma0_state = (kmb->layer_no == 0) ?
0252 LCD_VIDEO0_DMA0_STATE : LCD_VIDEO1_DMA0_STATE;
0253 dma1_state = (kmb->layer_no == 0) ?
0254 LCD_VIDEO0_DMA1_STATE : LCD_VIDEO1_DMA1_STATE;
0255
0256 do {
0257 kmb_write_lcd(kmb, LCD_FIFO_FLUSH, 1);
0258 val = kmb_read_lcd(kmb, dma0_state)
0259 & LCD_DMA_STATE_ACTIVE;
0260 val1 = kmb_read_lcd(kmb, dma1_state)
0261 & LCD_DMA_STATE_ACTIVE;
0262 } while ((val || val1));
0263
0264 kmb_clr_bitmask_lcd(kmb,
0265 LCD_LAYERn_DMA_CFG(kmb->layer_no),
0266 LCD_DMA_LAYER_ENABLE);
0267 kmb_write_lcd(kmb, LCD_FIFO_FLUSH, 1);
0268 kmb->kmb_flush_done = 1;
0269 kmb->kmb_under_flow = 0;
0270 }
0271 }
0272
0273 if (status & LCD_INT_LINE_CMP) {
0274
0275 kmb_write_lcd(kmb, LCD_INT_CLEAR, LCD_INT_LINE_CMP);
0276 }
0277
0278 if (status & LCD_INT_VERT_COMP) {
0279
0280 val = kmb_read_lcd(kmb, LCD_VSTATUS);
0281 val = (val & LCD_VSTATUS_VERTICAL_STATUS_MASK);
0282 switch (val) {
0283 case LCD_VSTATUS_COMPARE_VSYNC:
0284
0285 kmb_write_lcd(kmb, LCD_INT_CLEAR, LCD_INT_VERT_COMP);
0286 if (kmb->kmb_flush_done) {
0287 kmb_set_bitmask_lcd(kmb,
0288 LCD_LAYERn_DMA_CFG
0289 (kmb->layer_no),
0290 LCD_DMA_LAYER_ENABLE);
0291 kmb->kmb_flush_done = 0;
0292 }
0293 drm_crtc_handle_vblank(&kmb->crtc);
0294 break;
0295 case LCD_VSTATUS_COMPARE_BACKPORCH:
0296 case LCD_VSTATUS_COMPARE_ACTIVE:
0297 case LCD_VSTATUS_COMPARE_FRONT_PORCH:
0298 kmb_write_lcd(kmb, LCD_INT_CLEAR, LCD_INT_VERT_COMP);
0299 break;
0300 }
0301 }
0302 if (status & LCD_INT_DMA_ERR) {
0303 val =
0304 (status & LCD_INT_DMA_ERR &
0305 kmb_read_lcd(kmb, LCD_INT_ENABLE));
0306
0307 if (val & (LAYER0_DMA_FIFO_UNDERFLOW |
0308 LAYER0_DMA_CB_FIFO_UNDERFLOW |
0309 LAYER0_DMA_CR_FIFO_UNDERFLOW)) {
0310 kmb->kmb_under_flow++;
0311 drm_info(&kmb->drm,
0312 "!LAYER0:VL0 DMA UNDERFLOW val = 0x%lx,under_flow=%d",
0313 val, kmb->kmb_under_flow);
0314
0315 kmb_clr_bitmask_lcd(kmb, LCD_INT_ENABLE,
0316 LAYER0_DMA_FIFO_UNDERFLOW |
0317 LAYER0_DMA_CB_FIFO_UNDERFLOW |
0318 LAYER0_DMA_CR_FIFO_UNDERFLOW);
0319 kmb_set_bitmask_lcd(kmb, LCD_INT_CLEAR,
0320 LAYER0_DMA_CB_FIFO_UNDERFLOW |
0321 LAYER0_DMA_FIFO_UNDERFLOW |
0322 LAYER0_DMA_CR_FIFO_UNDERFLOW);
0323
0324 kmb_clr_bitmask_lcd(kmb, LCD_LAYERn_DMA_CFG(0),
0325 LCD_DMA_LAYER_CONT_PING_PONG_UPDATE);
0326
0327 kmb->layer_no = 0;
0328 }
0329
0330 if (val & LAYER0_DMA_FIFO_OVERFLOW)
0331 drm_dbg(&kmb->drm,
0332 "LAYER0:VL0 DMA OVERFLOW val = 0x%lx", val);
0333 if (val & LAYER0_DMA_CB_FIFO_OVERFLOW)
0334 drm_dbg(&kmb->drm,
0335 "LAYER0:VL0 DMA CB OVERFLOW val = 0x%lx", val);
0336 if (val & LAYER0_DMA_CR_FIFO_OVERFLOW)
0337 drm_dbg(&kmb->drm,
0338 "LAYER0:VL0 DMA CR OVERFLOW val = 0x%lx", val);
0339
0340
0341 if (val & (LAYER1_DMA_FIFO_UNDERFLOW |
0342 LAYER1_DMA_CB_FIFO_UNDERFLOW |
0343 LAYER1_DMA_CR_FIFO_UNDERFLOW)) {
0344 kmb->kmb_under_flow++;
0345 drm_info(&kmb->drm,
0346 "!LAYER1:VL1 DMA UNDERFLOW val = 0x%lx, under_flow=%d",
0347 val, kmb->kmb_under_flow);
0348
0349 kmb_clr_bitmask_lcd(kmb, LCD_INT_ENABLE,
0350 LAYER1_DMA_FIFO_UNDERFLOW |
0351 LAYER1_DMA_CB_FIFO_UNDERFLOW |
0352 LAYER1_DMA_CR_FIFO_UNDERFLOW);
0353 kmb_set_bitmask_lcd(kmb, LCD_INT_CLEAR,
0354 LAYER1_DMA_CB_FIFO_UNDERFLOW |
0355 LAYER1_DMA_FIFO_UNDERFLOW |
0356 LAYER1_DMA_CR_FIFO_UNDERFLOW);
0357
0358 kmb_clr_bitmask_lcd(kmb, LCD_LAYERn_DMA_CFG(1),
0359 LCD_DMA_LAYER_CONT_PING_PONG_UPDATE);
0360 kmb->layer_no = 1;
0361 }
0362
0363
0364 if (val & LAYER1_DMA_FIFO_OVERFLOW)
0365 drm_dbg(&kmb->drm,
0366 "LAYER1:VL1 DMA OVERFLOW val = 0x%lx", val);
0367 if (val & LAYER1_DMA_CB_FIFO_OVERFLOW)
0368 drm_dbg(&kmb->drm,
0369 "LAYER1:VL1 DMA CB OVERFLOW val = 0x%lx", val);
0370 if (val & LAYER1_DMA_CR_FIFO_OVERFLOW)
0371 drm_dbg(&kmb->drm,
0372 "LAYER1:VL1 DMA CR OVERFLOW val = 0x%lx", val);
0373
0374
0375 if (val & LAYER2_DMA_FIFO_UNDERFLOW)
0376 drm_dbg(&kmb->drm,
0377 "LAYER2:GL0 DMA UNDERFLOW val = 0x%lx", val);
0378 if (val & LAYER2_DMA_FIFO_OVERFLOW)
0379 drm_dbg(&kmb->drm,
0380 "LAYER2:GL0 DMA OVERFLOW val = 0x%lx", val);
0381
0382
0383 if (val & LAYER3_DMA_FIFO_UNDERFLOW)
0384 drm_dbg(&kmb->drm,
0385 "LAYER3:GL1 DMA UNDERFLOW val = 0x%lx", val);
0386 if (val & LAYER3_DMA_FIFO_OVERFLOW)
0387 drm_dbg(&kmb->drm,
0388 "LAYER3:GL1 DMA OVERFLOW val = 0x%lx", val);
0389 }
0390
0391 spin_unlock(&kmb->irq_lock);
0392
0393 if (status & LCD_INT_LAYER) {
0394
0395 kmb_write_lcd(kmb, LCD_INT_CLEAR, LCD_INT_LAYER);
0396 }
0397
0398
0399 kmb_set_bitmask_lcd(kmb, LCD_INT_CLEAR, 1);
0400 return IRQ_HANDLED;
0401 }
0402
0403
0404 static irqreturn_t kmb_isr(int irq, void *arg)
0405 {
0406 struct drm_device *dev = (struct drm_device *)arg;
0407
0408 handle_lcd_irq(dev);
0409 return IRQ_HANDLED;
0410 }
0411
0412 static void kmb_irq_reset(struct drm_device *drm)
0413 {
0414 kmb_write_lcd(to_kmb(drm), LCD_INT_CLEAR, 0xFFFF);
0415 kmb_write_lcd(to_kmb(drm), LCD_INT_ENABLE, 0);
0416 }
0417
0418 static int kmb_irq_install(struct drm_device *drm, unsigned int irq)
0419 {
0420 if (irq == IRQ_NOTCONNECTED)
0421 return -ENOTCONN;
0422
0423 kmb_irq_reset(drm);
0424
0425 return request_irq(irq, kmb_isr, 0, drm->driver->name, drm);
0426 }
0427
0428 static void kmb_irq_uninstall(struct drm_device *drm)
0429 {
0430 struct kmb_drm_private *kmb = to_kmb(drm);
0431
0432 kmb_irq_reset(drm);
0433 free_irq(kmb->irq_lcd, drm);
0434 }
0435
0436 DEFINE_DRM_GEM_CMA_FOPS(fops);
0437
0438 static const struct drm_driver kmb_driver = {
0439 .driver_features = DRIVER_GEM |
0440 DRIVER_MODESET | DRIVER_ATOMIC,
0441
0442 .fops = &fops,
0443 DRM_GEM_CMA_DRIVER_OPS_VMAP,
0444 .name = "kmb-drm",
0445 .desc = "KEEMBAY DISPLAY DRIVER",
0446 .date = DRIVER_DATE,
0447 .major = DRIVER_MAJOR,
0448 .minor = DRIVER_MINOR,
0449 };
0450
0451 static int kmb_remove(struct platform_device *pdev)
0452 {
0453 struct device *dev = &pdev->dev;
0454 struct drm_device *drm = dev_get_drvdata(dev);
0455 struct kmb_drm_private *kmb = to_kmb(drm);
0456
0457 drm_dev_unregister(drm);
0458 drm_kms_helper_poll_fini(drm);
0459 of_node_put(kmb->crtc.port);
0460 kmb->crtc.port = NULL;
0461 pm_runtime_get_sync(drm->dev);
0462 kmb_irq_uninstall(drm);
0463 pm_runtime_put_sync(drm->dev);
0464 pm_runtime_disable(drm->dev);
0465
0466 of_reserved_mem_device_release(drm->dev);
0467
0468
0469 kmb_display_clk_disable(kmb);
0470
0471 dev_set_drvdata(dev, NULL);
0472
0473
0474 kmb_dsi_host_unregister(kmb->kmb_dsi);
0475 drm_atomic_helper_shutdown(drm);
0476 return 0;
0477 }
0478
0479 static int kmb_probe(struct platform_device *pdev)
0480 {
0481 struct device *dev = get_device(&pdev->dev);
0482 struct kmb_drm_private *kmb;
0483 int ret = 0;
0484 struct device_node *dsi_in;
0485 struct device_node *dsi_node;
0486 struct platform_device *dsi_pdev;
0487
0488
0489
0490
0491
0492
0493
0494
0495 dsi_in = of_graph_get_endpoint_by_regs(dev->of_node, 0, 0);
0496 if (!dsi_in) {
0497 DRM_ERROR("Failed to get dsi_in node info from DT");
0498 return -EINVAL;
0499 }
0500 dsi_node = of_graph_get_remote_port_parent(dsi_in);
0501 if (!dsi_node) {
0502 of_node_put(dsi_in);
0503 DRM_ERROR("Failed to get dsi node from DT\n");
0504 return -EINVAL;
0505 }
0506
0507 dsi_pdev = of_find_device_by_node(dsi_node);
0508 if (!dsi_pdev) {
0509 of_node_put(dsi_in);
0510 of_node_put(dsi_node);
0511 DRM_ERROR("Failed to get dsi platform device\n");
0512 return -EINVAL;
0513 }
0514
0515 of_node_put(dsi_in);
0516 of_node_put(dsi_node);
0517 ret = kmb_dsi_host_bridge_init(get_device(&dsi_pdev->dev));
0518
0519 if (ret == -EPROBE_DEFER) {
0520 return -EPROBE_DEFER;
0521 } else if (ret) {
0522 DRM_ERROR("probe failed to initialize DSI host bridge\n");
0523 return ret;
0524 }
0525
0526
0527 kmb = devm_drm_dev_alloc(dev, &kmb_driver,
0528 struct kmb_drm_private, drm);
0529 if (IS_ERR(kmb))
0530 return PTR_ERR(kmb);
0531
0532 dev_set_drvdata(dev, &kmb->drm);
0533
0534
0535 kmb->kmb_dsi = kmb_dsi_init(dsi_pdev);
0536 if (IS_ERR(kmb->kmb_dsi)) {
0537 drm_err(&kmb->drm, "failed to initialize DSI\n");
0538 ret = PTR_ERR(kmb->kmb_dsi);
0539 goto err_free1;
0540 }
0541
0542 kmb->kmb_dsi->dev = &dsi_pdev->dev;
0543 kmb->kmb_dsi->pdev = dsi_pdev;
0544 ret = kmb_hw_init(&kmb->drm, 0);
0545 if (ret)
0546 goto err_free1;
0547
0548 ret = kmb_setup_mode_config(&kmb->drm);
0549 if (ret)
0550 goto err_free;
0551
0552 ret = kmb_irq_install(&kmb->drm, kmb->irq_lcd);
0553 if (ret < 0) {
0554 drm_err(&kmb->drm, "failed to install IRQ handler\n");
0555 goto err_irq;
0556 }
0557
0558 drm_kms_helper_poll_init(&kmb->drm);
0559
0560
0561 ret = drm_dev_register(&kmb->drm, 0);
0562 if (ret)
0563 goto err_register;
0564
0565 drm_fbdev_generic_setup(&kmb->drm, 0);
0566
0567 return 0;
0568
0569 err_register:
0570 drm_kms_helper_poll_fini(&kmb->drm);
0571 err_irq:
0572 pm_runtime_disable(kmb->drm.dev);
0573 err_free:
0574 drm_crtc_cleanup(&kmb->crtc);
0575 drm_mode_config_cleanup(&kmb->drm);
0576 err_free1:
0577 dev_set_drvdata(dev, NULL);
0578 kmb_dsi_host_unregister(kmb->kmb_dsi);
0579
0580 return ret;
0581 }
0582
0583 static const struct of_device_id kmb_of_match[] = {
0584 {.compatible = "intel,keembay-display"},
0585 {},
0586 };
0587
0588 MODULE_DEVICE_TABLE(of, kmb_of_match);
0589
0590 static int __maybe_unused kmb_pm_suspend(struct device *dev)
0591 {
0592 struct drm_device *drm = dev_get_drvdata(dev);
0593 struct kmb_drm_private *kmb = to_kmb(drm);
0594
0595 drm_kms_helper_poll_disable(drm);
0596
0597 kmb->state = drm_atomic_helper_suspend(drm);
0598 if (IS_ERR(kmb->state)) {
0599 drm_kms_helper_poll_enable(drm);
0600 return PTR_ERR(kmb->state);
0601 }
0602
0603 return 0;
0604 }
0605
0606 static int __maybe_unused kmb_pm_resume(struct device *dev)
0607 {
0608 struct drm_device *drm = dev_get_drvdata(dev);
0609 struct kmb_drm_private *kmb = drm ? to_kmb(drm) : NULL;
0610
0611 if (!kmb)
0612 return 0;
0613
0614 drm_atomic_helper_resume(drm, kmb->state);
0615 drm_kms_helper_poll_enable(drm);
0616
0617 return 0;
0618 }
0619
0620 static SIMPLE_DEV_PM_OPS(kmb_pm_ops, kmb_pm_suspend, kmb_pm_resume);
0621
0622 static struct platform_driver kmb_platform_driver = {
0623 .probe = kmb_probe,
0624 .remove = kmb_remove,
0625 .driver = {
0626 .name = "kmb-drm",
0627 .pm = &kmb_pm_ops,
0628 .of_match_table = kmb_of_match,
0629 },
0630 };
0631
0632 drm_module_platform_driver(kmb_platform_driver);
0633
0634 MODULE_AUTHOR("Intel Corporation");
0635 MODULE_DESCRIPTION("Keembay Display driver");
0636 MODULE_LICENSE("GPL v2");