1/* linux/drivers/video/exynos/exynos_mipi_dsi.c 2 * 3 * Samsung SoC MIPI-DSIM driver. 4 * 5 * Copyright (c) 2012 Samsung Electronics Co., Ltd 6 * 7 * InKi Dae, <inki.dae@samsung.com> 8 * Donghwa Lee, <dh09.lee@samsung.com> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13*/ 14 15#include <linux/module.h> 16#include <linux/kernel.h> 17#include <linux/errno.h> 18#include <linux/clk.h> 19#include <linux/mutex.h> 20#include <linux/wait.h> 21#include <linux/fs.h> 22#include <linux/mm.h> 23#include <linux/fb.h> 24#include <linux/ctype.h> 25#include <linux/platform_device.h> 26#include <linux/io.h> 27#include <linux/irq.h> 28#include <linux/memory.h> 29#include <linux/delay.h> 30#include <linux/interrupt.h> 31#include <linux/kthread.h> 32#include <linux/notifier.h> 33#include <linux/phy/phy.h> 34#include <linux/regulator/consumer.h> 35#include <linux/pm_runtime.h> 36#include <linux/err.h> 37 38#include <video/exynos_mipi_dsim.h> 39 40#include "exynos_mipi_dsi_common.h" 41#include "exynos_mipi_dsi_lowlevel.h" 42 43struct mipi_dsim_ddi { 44 int bus_id; 45 struct list_head list; 46 struct mipi_dsim_lcd_device *dsim_lcd_dev; 47 struct mipi_dsim_lcd_driver *dsim_lcd_drv; 48}; 49 50static LIST_HEAD(dsim_ddi_list); 51 52static DEFINE_MUTEX(mipi_dsim_lock); 53 54static struct mipi_dsim_platform_data *to_dsim_plat(struct platform_device 55 *pdev) 56{ 57 return pdev->dev.platform_data; 58} 59 60static struct regulator_bulk_data supplies[] = { 61 { .supply = "vdd11", }, 62 { .supply = "vdd18", }, 63}; 64 65static int exynos_mipi_regulator_enable(struct mipi_dsim_device *dsim) 66{ 67 int ret; 68 69 mutex_lock(&dsim->lock); 70 ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies); 71 mutex_unlock(&dsim->lock); 72 73 return ret; 74} 75 76static int exynos_mipi_regulator_disable(struct mipi_dsim_device *dsim) 77{ 78 int ret; 79 80 mutex_lock(&dsim->lock); 81 ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies); 82 mutex_unlock(&dsim->lock); 83 84 return ret; 85} 86 87/* update all register settings to MIPI DSI controller. */ 88static void exynos_mipi_update_cfg(struct mipi_dsim_device *dsim) 89{ 90 /* 91 * data from Display controller(FIMD) is not transferred in video mode 92 * but in case of command mode, all settings is not updated to 93 * registers. 94 */ 95 exynos_mipi_dsi_stand_by(dsim, 0); 96 97 exynos_mipi_dsi_init_dsim(dsim); 98 exynos_mipi_dsi_init_link(dsim); 99 100 exynos_mipi_dsi_set_hs_enable(dsim); 101 102 /* set display timing. */ 103 exynos_mipi_dsi_set_display_mode(dsim, dsim->dsim_config); 104 105 exynos_mipi_dsi_init_interrupt(dsim); 106 107 /* 108 * data from Display controller(FIMD) is transferred in video mode 109 * but in case of command mode, all settings are updated to registers. 110 */ 111 exynos_mipi_dsi_stand_by(dsim, 1); 112} 113 114static int exynos_mipi_dsi_early_blank_mode(struct mipi_dsim_device *dsim, 115 int power) 116{ 117 struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv; 118 struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev; 119 120 switch (power) { 121 case FB_BLANK_POWERDOWN: 122 if (dsim->suspended) 123 return 0; 124 125 if (client_drv && client_drv->suspend) 126 client_drv->suspend(client_dev); 127 128 clk_disable(dsim->clock); 129 130 exynos_mipi_regulator_disable(dsim); 131 132 dsim->suspended = true; 133 134 break; 135 default: 136 break; 137 } 138 139 return 0; 140} 141 142static int exynos_mipi_dsi_blank_mode(struct mipi_dsim_device *dsim, int power) 143{ 144 struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv; 145 struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev; 146 147 switch (power) { 148 case FB_BLANK_UNBLANK: 149 if (!dsim->suspended) 150 return 0; 151 152 /* lcd panel power on. */ 153 if (client_drv && client_drv->power_on) 154 client_drv->power_on(client_dev, 1); 155 156 exynos_mipi_regulator_enable(dsim); 157 158 /* enable MIPI-DSI PHY. */ 159 phy_power_on(dsim->phy); 160 161 clk_enable(dsim->clock); 162 163 exynos_mipi_update_cfg(dsim); 164 165 /* set lcd panel sequence commands. */ 166 if (client_drv && client_drv->set_sequence) 167 client_drv->set_sequence(client_dev); 168 169 dsim->suspended = false; 170 171 break; 172 case FB_BLANK_NORMAL: 173 /* TODO. */ 174 break; 175 default: 176 break; 177 } 178 179 return 0; 180} 181 182int exynos_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device *lcd_dev) 183{ 184 struct mipi_dsim_ddi *dsim_ddi; 185 186 if (!lcd_dev->name) { 187 pr_err("dsim_lcd_device name is NULL.\n"); 188 return -EFAULT; 189 } 190 191 dsim_ddi = kzalloc(sizeof(struct mipi_dsim_ddi), GFP_KERNEL); 192 if (!dsim_ddi) { 193 pr_err("failed to allocate dsim_ddi object.\n"); 194 return -ENOMEM; 195 } 196 197 dsim_ddi->dsim_lcd_dev = lcd_dev; 198 199 mutex_lock(&mipi_dsim_lock); 200 list_add_tail(&dsim_ddi->list, &dsim_ddi_list); 201 mutex_unlock(&mipi_dsim_lock); 202 203 return 0; 204} 205 206static struct mipi_dsim_ddi *exynos_mipi_dsi_find_lcd_device( 207 struct mipi_dsim_lcd_driver *lcd_drv) 208{ 209 struct mipi_dsim_ddi *dsim_ddi, *next; 210 struct mipi_dsim_lcd_device *lcd_dev; 211 212 mutex_lock(&mipi_dsim_lock); 213 214 list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) { 215 if (!dsim_ddi) 216 goto out; 217 218 lcd_dev = dsim_ddi->dsim_lcd_dev; 219 if (!lcd_dev) 220 continue; 221 222 if ((strcmp(lcd_drv->name, lcd_dev->name)) == 0) { 223 /** 224 * bus_id would be used to identify 225 * connected bus. 226 */ 227 dsim_ddi->bus_id = lcd_dev->bus_id; 228 mutex_unlock(&mipi_dsim_lock); 229 230 return dsim_ddi; 231 } 232 233 list_del(&dsim_ddi->list); 234 kfree(dsim_ddi); 235 } 236 237out: 238 mutex_unlock(&mipi_dsim_lock); 239 240 return NULL; 241} 242 243int exynos_mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver *lcd_drv) 244{ 245 struct mipi_dsim_ddi *dsim_ddi; 246 247 if (!lcd_drv->name) { 248 pr_err("dsim_lcd_driver name is NULL.\n"); 249 return -EFAULT; 250 } 251 252 dsim_ddi = exynos_mipi_dsi_find_lcd_device(lcd_drv); 253 if (!dsim_ddi) { 254 pr_err("mipi_dsim_ddi object not found.\n"); 255 return -EFAULT; 256 } 257 258 dsim_ddi->dsim_lcd_drv = lcd_drv; 259 260 pr_info("registered panel driver(%s) to mipi-dsi driver.\n", 261 lcd_drv->name); 262 263 return 0; 264 265} 266 267static struct mipi_dsim_ddi *exynos_mipi_dsi_bind_lcd_ddi( 268 struct mipi_dsim_device *dsim, 269 const char *name) 270{ 271 struct mipi_dsim_ddi *dsim_ddi, *next; 272 struct mipi_dsim_lcd_driver *lcd_drv; 273 struct mipi_dsim_lcd_device *lcd_dev; 274 int ret; 275 276 mutex_lock(&dsim->lock); 277 278 list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) { 279 lcd_drv = dsim_ddi->dsim_lcd_drv; 280 lcd_dev = dsim_ddi->dsim_lcd_dev; 281 if (!lcd_drv || !lcd_dev || 282 (dsim->id != dsim_ddi->bus_id)) 283 continue; 284 285 dev_dbg(dsim->dev, "lcd_drv->id = %d, lcd_dev->id = %d\n", 286 lcd_drv->id, lcd_dev->id); 287 dev_dbg(dsim->dev, "lcd_dev->bus_id = %d, dsim->id = %d\n", 288 lcd_dev->bus_id, dsim->id); 289 290 if ((strcmp(lcd_drv->name, name) == 0)) { 291 lcd_dev->master = dsim; 292 293 lcd_dev->dev.parent = dsim->dev; 294 dev_set_name(&lcd_dev->dev, "%s", lcd_drv->name); 295 296 ret = device_register(&lcd_dev->dev); 297 if (ret < 0) { 298 dev_err(dsim->dev, 299 "can't register %s, status %d\n", 300 dev_name(&lcd_dev->dev), ret); 301 mutex_unlock(&dsim->lock); 302 303 return NULL; 304 } 305 306 dsim->dsim_lcd_dev = lcd_dev; 307 dsim->dsim_lcd_drv = lcd_drv; 308 309 mutex_unlock(&dsim->lock); 310 311 return dsim_ddi; 312 } 313 } 314 315 mutex_unlock(&dsim->lock); 316 317 return NULL; 318} 319 320/* define MIPI-DSI Master operations. */ 321static struct mipi_dsim_master_ops master_ops = { 322 .cmd_read = exynos_mipi_dsi_rd_data, 323 .cmd_write = exynos_mipi_dsi_wr_data, 324 .get_dsim_frame_done = exynos_mipi_dsi_get_frame_done_status, 325 .clear_dsim_frame_done = exynos_mipi_dsi_clear_frame_done, 326 .set_early_blank_mode = exynos_mipi_dsi_early_blank_mode, 327 .set_blank_mode = exynos_mipi_dsi_blank_mode, 328}; 329 330static int exynos_mipi_dsi_probe(struct platform_device *pdev) 331{ 332 struct resource *res; 333 struct mipi_dsim_device *dsim; 334 struct mipi_dsim_config *dsim_config; 335 struct mipi_dsim_platform_data *dsim_pd; 336 struct mipi_dsim_ddi *dsim_ddi; 337 int ret = -EINVAL; 338 339 dsim = devm_kzalloc(&pdev->dev, sizeof(struct mipi_dsim_device), 340 GFP_KERNEL); 341 if (!dsim) { 342 dev_err(&pdev->dev, "failed to allocate dsim object.\n"); 343 return -ENOMEM; 344 } 345 346 dsim->pd = to_dsim_plat(pdev); 347 dsim->dev = &pdev->dev; 348 dsim->id = pdev->id; 349 350 /* get mipi_dsim_platform_data. */ 351 dsim_pd = (struct mipi_dsim_platform_data *)dsim->pd; 352 if (dsim_pd == NULL) { 353 dev_err(&pdev->dev, "failed to get platform data for dsim.\n"); 354 return -EINVAL; 355 } 356 /* get mipi_dsim_config. */ 357 dsim_config = dsim_pd->dsim_config; 358 if (dsim_config == NULL) { 359 dev_err(&pdev->dev, "failed to get dsim config data.\n"); 360 return -EINVAL; 361 } 362 363 dsim->dsim_config = dsim_config; 364 dsim->master_ops = &master_ops; 365 366 mutex_init(&dsim->lock); 367 368 ret = devm_regulator_bulk_get(&pdev->dev, ARRAY_SIZE(supplies), 369 supplies); 370 if (ret) { 371 dev_err(&pdev->dev, "Failed to get regulators: %d\n", ret); 372 return ret; 373 } 374 375 dsim->phy = devm_phy_get(&pdev->dev, "dsim"); 376 if (IS_ERR(dsim->phy)) 377 return PTR_ERR(dsim->phy); 378 379 dsim->clock = devm_clk_get(&pdev->dev, "dsim0"); 380 if (IS_ERR(dsim->clock)) { 381 dev_err(&pdev->dev, "failed to get dsim clock source\n"); 382 return -ENODEV; 383 } 384 385 clk_enable(dsim->clock); 386 387 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 388 389 dsim->reg_base = devm_ioremap_resource(&pdev->dev, res); 390 if (IS_ERR(dsim->reg_base)) { 391 ret = PTR_ERR(dsim->reg_base); 392 goto error; 393 } 394 395 mutex_init(&dsim->lock); 396 397 /* bind lcd ddi matched with panel name. */ 398 dsim_ddi = exynos_mipi_dsi_bind_lcd_ddi(dsim, dsim_pd->lcd_panel_name); 399 if (!dsim_ddi) { 400 dev_err(&pdev->dev, "mipi_dsim_ddi object not found.\n"); 401 ret = -EINVAL; 402 goto error; 403 } 404 405 dsim->irq = platform_get_irq(pdev, 0); 406 if (IS_ERR_VALUE(dsim->irq)) { 407 dev_err(&pdev->dev, "failed to request dsim irq resource\n"); 408 ret = -EINVAL; 409 goto error; 410 } 411 412 init_completion(&dsim_wr_comp); 413 init_completion(&dsim_rd_comp); 414 platform_set_drvdata(pdev, dsim); 415 416 ret = devm_request_irq(&pdev->dev, dsim->irq, 417 exynos_mipi_dsi_interrupt_handler, 418 IRQF_SHARED, dev_name(&pdev->dev), dsim); 419 if (ret != 0) { 420 dev_err(&pdev->dev, "failed to request dsim irq\n"); 421 ret = -EINVAL; 422 goto error; 423 } 424 425 /* enable interrupts */ 426 exynos_mipi_dsi_init_interrupt(dsim); 427 428 /* initialize mipi-dsi client(lcd panel). */ 429 if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->probe) 430 dsim_ddi->dsim_lcd_drv->probe(dsim_ddi->dsim_lcd_dev); 431 432 /* in case mipi-dsi has been enabled by bootloader */ 433 if (dsim_pd->enabled) { 434 exynos_mipi_regulator_enable(dsim); 435 goto done; 436 } 437 438 /* lcd panel power on. */ 439 if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->power_on) 440 dsim_ddi->dsim_lcd_drv->power_on(dsim_ddi->dsim_lcd_dev, 1); 441 442 exynos_mipi_regulator_enable(dsim); 443 444 /* enable MIPI-DSI PHY. */ 445 phy_power_on(dsim->phy); 446 447 exynos_mipi_update_cfg(dsim); 448 449 /* set lcd panel sequence commands. */ 450 if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->set_sequence) 451 dsim_ddi->dsim_lcd_drv->set_sequence(dsim_ddi->dsim_lcd_dev); 452 453 dsim->suspended = false; 454 455done: 456 platform_set_drvdata(pdev, dsim); 457 458 dev_dbg(&pdev->dev, "%s() completed successfully (%s mode)\n", __func__, 459 dsim_config->e_interface == DSIM_COMMAND ? "CPU" : "RGB"); 460 461 return 0; 462 463error: 464 clk_disable(dsim->clock); 465 return ret; 466} 467 468static int exynos_mipi_dsi_remove(struct platform_device *pdev) 469{ 470 struct mipi_dsim_device *dsim = platform_get_drvdata(pdev); 471 struct mipi_dsim_ddi *dsim_ddi, *next; 472 struct mipi_dsim_lcd_driver *dsim_lcd_drv; 473 474 clk_disable(dsim->clock); 475 476 list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) { 477 if (dsim_ddi) { 478 if (dsim->id != dsim_ddi->bus_id) 479 continue; 480 481 dsim_lcd_drv = dsim_ddi->dsim_lcd_drv; 482 483 if (dsim_lcd_drv->remove) 484 dsim_lcd_drv->remove(dsim_ddi->dsim_lcd_dev); 485 486 kfree(dsim_ddi); 487 } 488 } 489 490 return 0; 491} 492 493#ifdef CONFIG_PM_SLEEP 494static int exynos_mipi_dsi_suspend(struct device *dev) 495{ 496 struct platform_device *pdev = to_platform_device(dev); 497 struct mipi_dsim_device *dsim = platform_get_drvdata(pdev); 498 struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv; 499 struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev; 500 501 disable_irq(dsim->irq); 502 503 if (dsim->suspended) 504 return 0; 505 506 if (client_drv && client_drv->suspend) 507 client_drv->suspend(client_dev); 508 509 /* disable MIPI-DSI PHY. */ 510 phy_power_off(dsim->phy); 511 512 clk_disable(dsim->clock); 513 514 exynos_mipi_regulator_disable(dsim); 515 516 dsim->suspended = true; 517 518 return 0; 519} 520 521static int exynos_mipi_dsi_resume(struct device *dev) 522{ 523 struct platform_device *pdev = to_platform_device(dev); 524 struct mipi_dsim_device *dsim = platform_get_drvdata(pdev); 525 struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv; 526 struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev; 527 528 enable_irq(dsim->irq); 529 530 if (!dsim->suspended) 531 return 0; 532 533 /* lcd panel power on. */ 534 if (client_drv && client_drv->power_on) 535 client_drv->power_on(client_dev, 1); 536 537 exynos_mipi_regulator_enable(dsim); 538 539 /* enable MIPI-DSI PHY. */ 540 phy_power_on(dsim->phy); 541 542 clk_enable(dsim->clock); 543 544 exynos_mipi_update_cfg(dsim); 545 546 /* set lcd panel sequence commands. */ 547 if (client_drv && client_drv->set_sequence) 548 client_drv->set_sequence(client_dev); 549 550 dsim->suspended = false; 551 552 return 0; 553} 554#endif 555 556static const struct dev_pm_ops exynos_mipi_dsi_pm_ops = { 557 SET_SYSTEM_SLEEP_PM_OPS(exynos_mipi_dsi_suspend, exynos_mipi_dsi_resume) 558}; 559 560static struct platform_driver exynos_mipi_dsi_driver = { 561 .probe = exynos_mipi_dsi_probe, 562 .remove = exynos_mipi_dsi_remove, 563 .driver = { 564 .name = "exynos-mipi-dsim", 565 .pm = &exynos_mipi_dsi_pm_ops, 566 }, 567}; 568 569module_platform_driver(exynos_mipi_dsi_driver); 570 571MODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>"); 572MODULE_DESCRIPTION("Samsung SoC MIPI-DSI driver"); 573MODULE_LICENSE("GPL"); 574