Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.7-rc7 610 lines 14 kB view raw
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/regulator/consumer.h> 34#include <linux/pm_runtime.h> 35 36#include <video/exynos_mipi_dsim.h> 37 38#include <plat/fb.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 platform_device *pdev = to_platform_device(dsim->dev); 145 struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv; 146 struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev; 147 148 switch (power) { 149 case FB_BLANK_UNBLANK: 150 if (!dsim->suspended) 151 return 0; 152 153 /* lcd panel power on. */ 154 if (client_drv && client_drv->power_on) 155 client_drv->power_on(client_dev, 1); 156 157 exynos_mipi_regulator_enable(dsim); 158 159 /* enable MIPI-DSI PHY. */ 160 if (dsim->pd->phy_enable) 161 dsim->pd->phy_enable(pdev, true); 162 163 clk_enable(dsim->clock); 164 165 exynos_mipi_update_cfg(dsim); 166 167 /* set lcd panel sequence commands. */ 168 if (client_drv && client_drv->set_sequence) 169 client_drv->set_sequence(client_dev); 170 171 dsim->suspended = false; 172 173 break; 174 case FB_BLANK_NORMAL: 175 /* TODO. */ 176 break; 177 default: 178 break; 179 } 180 181 return 0; 182} 183 184int exynos_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device *lcd_dev) 185{ 186 struct mipi_dsim_ddi *dsim_ddi; 187 188 if (!lcd_dev->name) { 189 pr_err("dsim_lcd_device name is NULL.\n"); 190 return -EFAULT; 191 } 192 193 dsim_ddi = kzalloc(sizeof(struct mipi_dsim_ddi), GFP_KERNEL); 194 if (!dsim_ddi) { 195 pr_err("failed to allocate dsim_ddi object.\n"); 196 return -ENOMEM; 197 } 198 199 dsim_ddi->dsim_lcd_dev = lcd_dev; 200 201 mutex_lock(&mipi_dsim_lock); 202 list_add_tail(&dsim_ddi->list, &dsim_ddi_list); 203 mutex_unlock(&mipi_dsim_lock); 204 205 return 0; 206} 207 208static struct mipi_dsim_ddi *exynos_mipi_dsi_find_lcd_device( 209 struct mipi_dsim_lcd_driver *lcd_drv) 210{ 211 struct mipi_dsim_ddi *dsim_ddi, *next; 212 struct mipi_dsim_lcd_device *lcd_dev; 213 214 mutex_lock(&mipi_dsim_lock); 215 216 list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) { 217 if (!dsim_ddi) 218 goto out; 219 220 lcd_dev = dsim_ddi->dsim_lcd_dev; 221 if (!lcd_dev) 222 continue; 223 224 if ((strcmp(lcd_drv->name, lcd_dev->name)) == 0) { 225 /** 226 * bus_id would be used to identify 227 * connected bus. 228 */ 229 dsim_ddi->bus_id = lcd_dev->bus_id; 230 mutex_unlock(&mipi_dsim_lock); 231 232 return dsim_ddi; 233 } 234 235 list_del(&dsim_ddi->list); 236 kfree(dsim_ddi); 237 } 238 239out: 240 mutex_unlock(&mipi_dsim_lock); 241 242 return NULL; 243} 244 245int exynos_mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver *lcd_drv) 246{ 247 struct mipi_dsim_ddi *dsim_ddi; 248 249 if (!lcd_drv->name) { 250 pr_err("dsim_lcd_driver name is NULL.\n"); 251 return -EFAULT; 252 } 253 254 dsim_ddi = exynos_mipi_dsi_find_lcd_device(lcd_drv); 255 if (!dsim_ddi) { 256 pr_err("mipi_dsim_ddi object not found.\n"); 257 return -EFAULT; 258 } 259 260 dsim_ddi->dsim_lcd_drv = lcd_drv; 261 262 pr_info("registered panel driver(%s) to mipi-dsi driver.\n", 263 lcd_drv->name); 264 265 return 0; 266 267} 268 269static struct mipi_dsim_ddi *exynos_mipi_dsi_bind_lcd_ddi( 270 struct mipi_dsim_device *dsim, 271 const char *name) 272{ 273 struct mipi_dsim_ddi *dsim_ddi, *next; 274 struct mipi_dsim_lcd_driver *lcd_drv; 275 struct mipi_dsim_lcd_device *lcd_dev; 276 int ret; 277 278 mutex_lock(&dsim->lock); 279 280 list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) { 281 lcd_drv = dsim_ddi->dsim_lcd_drv; 282 lcd_dev = dsim_ddi->dsim_lcd_dev; 283 if (!lcd_drv || !lcd_dev || 284 (dsim->id != dsim_ddi->bus_id)) 285 continue; 286 287 dev_dbg(dsim->dev, "lcd_drv->id = %d, lcd_dev->id = %d\n", 288 lcd_drv->id, lcd_dev->id); 289 dev_dbg(dsim->dev, "lcd_dev->bus_id = %d, dsim->id = %d\n", 290 lcd_dev->bus_id, dsim->id); 291 292 if ((strcmp(lcd_drv->name, name) == 0)) { 293 lcd_dev->master = dsim; 294 295 lcd_dev->dev.parent = dsim->dev; 296 dev_set_name(&lcd_dev->dev, "%s", lcd_drv->name); 297 298 ret = device_register(&lcd_dev->dev); 299 if (ret < 0) { 300 dev_err(dsim->dev, 301 "can't register %s, status %d\n", 302 dev_name(&lcd_dev->dev), ret); 303 mutex_unlock(&dsim->lock); 304 305 return NULL; 306 } 307 308 dsim->dsim_lcd_dev = lcd_dev; 309 dsim->dsim_lcd_drv = lcd_drv; 310 311 mutex_unlock(&dsim->lock); 312 313 return dsim_ddi; 314 } 315 } 316 317 mutex_unlock(&dsim->lock); 318 319 return NULL; 320} 321 322/* define MIPI-DSI Master operations. */ 323static struct mipi_dsim_master_ops master_ops = { 324 .cmd_read = exynos_mipi_dsi_rd_data, 325 .cmd_write = exynos_mipi_dsi_wr_data, 326 .get_dsim_frame_done = exynos_mipi_dsi_get_frame_done_status, 327 .clear_dsim_frame_done = exynos_mipi_dsi_clear_frame_done, 328 .set_early_blank_mode = exynos_mipi_dsi_early_blank_mode, 329 .set_blank_mode = exynos_mipi_dsi_blank_mode, 330}; 331 332static int exynos_mipi_dsi_probe(struct platform_device *pdev) 333{ 334 struct resource *res; 335 struct mipi_dsim_device *dsim; 336 struct mipi_dsim_config *dsim_config; 337 struct mipi_dsim_platform_data *dsim_pd; 338 struct mipi_dsim_ddi *dsim_ddi; 339 int ret = -EINVAL; 340 341 dsim = kzalloc(sizeof(struct mipi_dsim_device), GFP_KERNEL); 342 if (!dsim) { 343 dev_err(&pdev->dev, "failed to allocate dsim object.\n"); 344 return -ENOMEM; 345 } 346 347 dsim->pd = to_dsim_plat(pdev); 348 dsim->dev = &pdev->dev; 349 dsim->id = pdev->id; 350 351 /* get mipi_dsim_platform_data. */ 352 dsim_pd = (struct mipi_dsim_platform_data *)dsim->pd; 353 if (dsim_pd == NULL) { 354 dev_err(&pdev->dev, "failed to get platform data for dsim.\n"); 355 goto err_clock_get; 356 } 357 /* get mipi_dsim_config. */ 358 dsim_config = dsim_pd->dsim_config; 359 if (dsim_config == NULL) { 360 dev_err(&pdev->dev, "failed to get dsim config data.\n"); 361 goto err_clock_get; 362 } 363 364 dsim->dsim_config = dsim_config; 365 dsim->master_ops = &master_ops; 366 367 mutex_init(&dsim->lock); 368 369 ret = regulator_bulk_get(&pdev->dev, ARRAY_SIZE(supplies), supplies); 370 if (ret) { 371 dev_err(&pdev->dev, "Failed to get regulators: %d\n", ret); 372 goto err_clock_get; 373 } 374 375 dsim->clock = clk_get(&pdev->dev, "dsim0"); 376 if (IS_ERR(dsim->clock)) { 377 dev_err(&pdev->dev, "failed to get dsim clock source\n"); 378 ret = -ENODEV; 379 goto err_clock_get; 380 } 381 382 clk_enable(dsim->clock); 383 384 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 385 if (!res) { 386 dev_err(&pdev->dev, "failed to get io memory region\n"); 387 ret = -ENODEV; 388 goto err_platform_get; 389 } 390 391 dsim->res = request_mem_region(res->start, resource_size(res), 392 dev_name(&pdev->dev)); 393 if (!dsim->res) { 394 dev_err(&pdev->dev, "failed to request io memory region\n"); 395 ret = -ENOMEM; 396 goto err_mem_region; 397 } 398 399 dsim->reg_base = ioremap(res->start, resource_size(res)); 400 if (!dsim->reg_base) { 401 dev_err(&pdev->dev, "failed to remap io region\n"); 402 ret = -ENOMEM; 403 goto err_ioremap; 404 } 405 406 mutex_init(&dsim->lock); 407 408 /* bind lcd ddi matched with panel name. */ 409 dsim_ddi = exynos_mipi_dsi_bind_lcd_ddi(dsim, dsim_pd->lcd_panel_name); 410 if (!dsim_ddi) { 411 dev_err(&pdev->dev, "mipi_dsim_ddi object not found.\n"); 412 ret = -EINVAL; 413 goto err_bind; 414 } 415 416 dsim->irq = platform_get_irq(pdev, 0); 417 if (dsim->irq < 0) { 418 dev_err(&pdev->dev, "failed to request dsim irq resource\n"); 419 ret = -EINVAL; 420 goto err_platform_get_irq; 421 } 422 423 init_completion(&dsim_wr_comp); 424 init_completion(&dsim_rd_comp); 425 platform_set_drvdata(pdev, dsim); 426 427 ret = request_irq(dsim->irq, exynos_mipi_dsi_interrupt_handler, 428 IRQF_SHARED, dev_name(&pdev->dev), dsim); 429 if (ret != 0) { 430 dev_err(&pdev->dev, "failed to request dsim irq\n"); 431 ret = -EINVAL; 432 goto err_bind; 433 } 434 435 /* enable interrupts */ 436 exynos_mipi_dsi_init_interrupt(dsim); 437 438 /* initialize mipi-dsi client(lcd panel). */ 439 if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->probe) 440 dsim_ddi->dsim_lcd_drv->probe(dsim_ddi->dsim_lcd_dev); 441 442 /* in case mipi-dsi has been enabled by bootloader */ 443 if (dsim_pd->enabled) { 444 exynos_mipi_regulator_enable(dsim); 445 goto done; 446 } 447 448 /* lcd panel power on. */ 449 if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->power_on) 450 dsim_ddi->dsim_lcd_drv->power_on(dsim_ddi->dsim_lcd_dev, 1); 451 452 exynos_mipi_regulator_enable(dsim); 453 454 /* enable MIPI-DSI PHY. */ 455 if (dsim->pd->phy_enable) 456 dsim->pd->phy_enable(pdev, true); 457 458 exynos_mipi_update_cfg(dsim); 459 460 /* set lcd panel sequence commands. */ 461 if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->set_sequence) 462 dsim_ddi->dsim_lcd_drv->set_sequence(dsim_ddi->dsim_lcd_dev); 463 464 dsim->suspended = false; 465 466done: 467 platform_set_drvdata(pdev, dsim); 468 469 dev_dbg(&pdev->dev, "%s() completed successfully (%s mode)\n", __func__, 470 dsim_config->e_interface == DSIM_COMMAND ? "CPU" : "RGB"); 471 472 return 0; 473 474err_bind: 475 iounmap(dsim->reg_base); 476 477err_ioremap: 478 release_mem_region(dsim->res->start, resource_size(dsim->res)); 479 480err_mem_region: 481 release_resource(dsim->res); 482 483err_platform_get: 484 clk_disable(dsim->clock); 485 clk_put(dsim->clock); 486err_clock_get: 487 kfree(dsim); 488 489err_platform_get_irq: 490 return ret; 491} 492 493static int __devexit exynos_mipi_dsi_remove(struct platform_device *pdev) 494{ 495 struct mipi_dsim_device *dsim = platform_get_drvdata(pdev); 496 struct mipi_dsim_ddi *dsim_ddi, *next; 497 struct mipi_dsim_lcd_driver *dsim_lcd_drv; 498 499 iounmap(dsim->reg_base); 500 501 clk_disable(dsim->clock); 502 clk_put(dsim->clock); 503 504 release_resource(dsim->res); 505 release_mem_region(dsim->res->start, resource_size(dsim->res)); 506 507 list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) { 508 if (dsim_ddi) { 509 if (dsim->id != dsim_ddi->bus_id) 510 continue; 511 512 dsim_lcd_drv = dsim_ddi->dsim_lcd_drv; 513 514 if (dsim_lcd_drv->remove) 515 dsim_lcd_drv->remove(dsim_ddi->dsim_lcd_dev); 516 517 kfree(dsim_ddi); 518 } 519 } 520 521 regulator_bulk_free(ARRAY_SIZE(supplies), supplies); 522 kfree(dsim); 523 524 return 0; 525} 526 527#ifdef CONFIG_PM_SLEEP 528static int exynos_mipi_dsi_suspend(struct device *dev) 529{ 530 struct platform_device *pdev = to_platform_device(dev); 531 struct mipi_dsim_device *dsim = platform_get_drvdata(pdev); 532 struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv; 533 struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev; 534 535 disable_irq(dsim->irq); 536 537 if (dsim->suspended) 538 return 0; 539 540 if (client_drv && client_drv->suspend) 541 client_drv->suspend(client_dev); 542 543 /* enable MIPI-DSI PHY. */ 544 if (dsim->pd->phy_enable) 545 dsim->pd->phy_enable(pdev, false); 546 547 clk_disable(dsim->clock); 548 549 exynos_mipi_regulator_disable(dsim); 550 551 dsim->suspended = true; 552 553 return 0; 554} 555 556static int exynos_mipi_dsi_resume(struct device *dev) 557{ 558 struct platform_device *pdev = to_platform_device(dev); 559 struct mipi_dsim_device *dsim = platform_get_drvdata(pdev); 560 struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv; 561 struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev; 562 563 enable_irq(dsim->irq); 564 565 if (!dsim->suspended) 566 return 0; 567 568 /* lcd panel power on. */ 569 if (client_drv && client_drv->power_on) 570 client_drv->power_on(client_dev, 1); 571 572 exynos_mipi_regulator_enable(dsim); 573 574 /* enable MIPI-DSI PHY. */ 575 if (dsim->pd->phy_enable) 576 dsim->pd->phy_enable(pdev, true); 577 578 clk_enable(dsim->clock); 579 580 exynos_mipi_update_cfg(dsim); 581 582 /* set lcd panel sequence commands. */ 583 if (client_drv && client_drv->set_sequence) 584 client_drv->set_sequence(client_dev); 585 586 dsim->suspended = false; 587 588 return 0; 589} 590#endif 591 592static const struct dev_pm_ops exynos_mipi_dsi_pm_ops = { 593 SET_SYSTEM_SLEEP_PM_OPS(exynos_mipi_dsi_suspend, exynos_mipi_dsi_resume) 594}; 595 596static struct platform_driver exynos_mipi_dsi_driver = { 597 .probe = exynos_mipi_dsi_probe, 598 .remove = __devexit_p(exynos_mipi_dsi_remove), 599 .driver = { 600 .name = "exynos-mipi-dsim", 601 .owner = THIS_MODULE, 602 .pm = &exynos_mipi_dsi_pm_ops, 603 }, 604}; 605 606module_platform_driver(exynos_mipi_dsi_driver); 607 608MODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>"); 609MODULE_DESCRIPTION("Samusung SoC MIPI-DSI driver"); 610MODULE_LICENSE("GPL");