dpi.c (18414B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * linux/drivers/video/omap2/dss/dpi.c 4 * 5 * Copyright (C) 2009 Nokia Corporation 6 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> 7 * 8 * Some code and ideas taken from drivers/video/omap/ driver 9 * by Imre Deak. 10 */ 11 12#define DSS_SUBSYS_NAME "DPI" 13 14#include <linux/kernel.h> 15#include <linux/delay.h> 16#include <linux/export.h> 17#include <linux/err.h> 18#include <linux/errno.h> 19#include <linux/platform_device.h> 20#include <linux/regulator/consumer.h> 21#include <linux/string.h> 22#include <linux/of.h> 23#include <linux/clk.h> 24#include <linux/component.h> 25 26#include <video/omapfb_dss.h> 27 28#include "dss.h" 29#include "dss_features.h" 30 31#define HSDIV_DISPC 0 32 33struct dpi_data { 34 struct platform_device *pdev; 35 36 struct regulator *vdds_dsi_reg; 37 struct dss_pll *pll; 38 39 struct mutex lock; 40 41 struct omap_video_timings timings; 42 struct dss_lcd_mgr_config mgr_config; 43 int data_lines; 44 45 struct omap_dss_device output; 46 47 bool port_initialized; 48}; 49 50static struct dpi_data *dpi_get_data_from_dssdev(struct omap_dss_device *dssdev) 51{ 52 return container_of(dssdev, struct dpi_data, output); 53} 54 55/* only used in non-DT mode */ 56static struct dpi_data *dpi_get_data_from_pdev(struct platform_device *pdev) 57{ 58 return platform_get_drvdata(pdev); 59} 60 61static struct dss_pll *dpi_get_pll(enum omap_channel channel) 62{ 63 /* 64 * XXX we can't currently use DSI PLL for DPI with OMAP3, as the DSI PLL 65 * would also be used for DISPC fclk. Meaning, when the DPI output is 66 * disabled, DISPC clock will be disabled, and TV out will stop. 67 */ 68 switch (omapdss_get_version()) { 69 case OMAPDSS_VER_OMAP24xx: 70 case OMAPDSS_VER_OMAP34xx_ES1: 71 case OMAPDSS_VER_OMAP34xx_ES3: 72 case OMAPDSS_VER_OMAP3630: 73 case OMAPDSS_VER_AM35xx: 74 case OMAPDSS_VER_AM43xx: 75 return NULL; 76 77 case OMAPDSS_VER_OMAP4430_ES1: 78 case OMAPDSS_VER_OMAP4430_ES2: 79 case OMAPDSS_VER_OMAP4: 80 switch (channel) { 81 case OMAP_DSS_CHANNEL_LCD: 82 return dss_pll_find("dsi0"); 83 case OMAP_DSS_CHANNEL_LCD2: 84 return dss_pll_find("dsi1"); 85 default: 86 return NULL; 87 } 88 89 case OMAPDSS_VER_OMAP5: 90 switch (channel) { 91 case OMAP_DSS_CHANNEL_LCD: 92 return dss_pll_find("dsi0"); 93 case OMAP_DSS_CHANNEL_LCD3: 94 return dss_pll_find("dsi1"); 95 default: 96 return NULL; 97 } 98 99 case OMAPDSS_VER_DRA7xx: 100 switch (channel) { 101 case OMAP_DSS_CHANNEL_LCD: 102 case OMAP_DSS_CHANNEL_LCD2: 103 return dss_pll_find("video0"); 104 case OMAP_DSS_CHANNEL_LCD3: 105 return dss_pll_find("video1"); 106 default: 107 return NULL; 108 } 109 110 default: 111 return NULL; 112 } 113} 114 115static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel) 116{ 117 switch (channel) { 118 case OMAP_DSS_CHANNEL_LCD: 119 return OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC; 120 case OMAP_DSS_CHANNEL_LCD2: 121 return OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC; 122 case OMAP_DSS_CHANNEL_LCD3: 123 return OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC; 124 default: 125 /* this shouldn't happen */ 126 WARN_ON(1); 127 return OMAP_DSS_CLK_SRC_FCK; 128 } 129} 130 131struct dpi_clk_calc_ctx { 132 struct dss_pll *pll; 133 134 /* inputs */ 135 136 unsigned long pck_min, pck_max; 137 138 /* outputs */ 139 140 struct dss_pll_clock_info dsi_cinfo; 141 unsigned long fck; 142 struct dispc_clock_info dispc_cinfo; 143}; 144 145static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck, 146 unsigned long pck, void *data) 147{ 148 struct dpi_clk_calc_ctx *ctx = data; 149 150 /* 151 * Odd dividers give us uneven duty cycle, causing problem when level 152 * shifted. So skip all odd dividers when the pixel clock is on the 153 * higher side. 154 */ 155 if (ctx->pck_min >= 100000000) { 156 if (lckd > 1 && lckd % 2 != 0) 157 return false; 158 159 if (pckd > 1 && pckd % 2 != 0) 160 return false; 161 } 162 163 ctx->dispc_cinfo.lck_div = lckd; 164 ctx->dispc_cinfo.pck_div = pckd; 165 ctx->dispc_cinfo.lck = lck; 166 ctx->dispc_cinfo.pck = pck; 167 168 return true; 169} 170 171 172static bool dpi_calc_hsdiv_cb(int m_dispc, unsigned long dispc, 173 void *data) 174{ 175 struct dpi_clk_calc_ctx *ctx = data; 176 177 /* 178 * Odd dividers give us uneven duty cycle, causing problem when level 179 * shifted. So skip all odd dividers when the pixel clock is on the 180 * higher side. 181 */ 182 if (m_dispc > 1 && m_dispc % 2 != 0 && ctx->pck_min >= 100000000) 183 return false; 184 185 ctx->dsi_cinfo.mX[HSDIV_DISPC] = m_dispc; 186 ctx->dsi_cinfo.clkout[HSDIV_DISPC] = dispc; 187 188 return dispc_div_calc(dispc, ctx->pck_min, ctx->pck_max, 189 dpi_calc_dispc_cb, ctx); 190} 191 192 193static bool dpi_calc_pll_cb(int n, int m, unsigned long fint, 194 unsigned long clkdco, 195 void *data) 196{ 197 struct dpi_clk_calc_ctx *ctx = data; 198 199 ctx->dsi_cinfo.n = n; 200 ctx->dsi_cinfo.m = m; 201 ctx->dsi_cinfo.fint = fint; 202 ctx->dsi_cinfo.clkdco = clkdco; 203 204 return dss_pll_hsdiv_calc(ctx->pll, clkdco, 205 ctx->pck_min, dss_feat_get_param_max(FEAT_PARAM_DSS_FCK), 206 dpi_calc_hsdiv_cb, ctx); 207} 208 209static bool dpi_calc_dss_cb(unsigned long fck, void *data) 210{ 211 struct dpi_clk_calc_ctx *ctx = data; 212 213 ctx->fck = fck; 214 215 return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max, 216 dpi_calc_dispc_cb, ctx); 217} 218 219static bool dpi_dsi_clk_calc(struct dpi_data *dpi, unsigned long pck, 220 struct dpi_clk_calc_ctx *ctx) 221{ 222 unsigned long clkin; 223 unsigned long pll_min, pll_max; 224 225 memset(ctx, 0, sizeof(*ctx)); 226 ctx->pll = dpi->pll; 227 ctx->pck_min = pck - 1000; 228 ctx->pck_max = pck + 1000; 229 230 pll_min = 0; 231 pll_max = 0; 232 233 clkin = clk_get_rate(ctx->pll->clkin); 234 235 return dss_pll_calc(ctx->pll, clkin, 236 pll_min, pll_max, 237 dpi_calc_pll_cb, ctx); 238} 239 240static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx) 241{ 242 int i; 243 244 /* 245 * DSS fck gives us very few possibilities, so finding a good pixel 246 * clock may not be possible. We try multiple times to find the clock, 247 * each time widening the pixel clock range we look for, up to 248 * +/- ~15MHz. 249 */ 250 251 for (i = 0; i < 25; ++i) { 252 bool ok; 253 254 memset(ctx, 0, sizeof(*ctx)); 255 if (pck > 1000 * i * i * i) 256 ctx->pck_min = max(pck - 1000 * i * i * i, 0lu); 257 else 258 ctx->pck_min = 0; 259 ctx->pck_max = pck + 1000 * i * i * i; 260 261 ok = dss_div_calc(pck, ctx->pck_min, dpi_calc_dss_cb, ctx); 262 if (ok) 263 return ok; 264 } 265 266 return false; 267} 268 269 270 271static int dpi_set_dsi_clk(struct dpi_data *dpi, enum omap_channel channel, 272 unsigned long pck_req, unsigned long *fck, int *lck_div, 273 int *pck_div) 274{ 275 struct dpi_clk_calc_ctx ctx; 276 int r; 277 bool ok; 278 279 ok = dpi_dsi_clk_calc(dpi, pck_req, &ctx); 280 if (!ok) 281 return -EINVAL; 282 283 r = dss_pll_set_config(dpi->pll, &ctx.dsi_cinfo); 284 if (r) 285 return r; 286 287 dss_select_lcd_clk_source(channel, 288 dpi_get_alt_clk_src(channel)); 289 290 dpi->mgr_config.clock_info = ctx.dispc_cinfo; 291 292 *fck = ctx.dsi_cinfo.clkout[HSDIV_DISPC]; 293 *lck_div = ctx.dispc_cinfo.lck_div; 294 *pck_div = ctx.dispc_cinfo.pck_div; 295 296 return 0; 297} 298 299static int dpi_set_dispc_clk(struct dpi_data *dpi, unsigned long pck_req, 300 unsigned long *fck, int *lck_div, int *pck_div) 301{ 302 struct dpi_clk_calc_ctx ctx; 303 int r; 304 bool ok; 305 306 ok = dpi_dss_clk_calc(pck_req, &ctx); 307 if (!ok) 308 return -EINVAL; 309 310 r = dss_set_fck_rate(ctx.fck); 311 if (r) 312 return r; 313 314 dpi->mgr_config.clock_info = ctx.dispc_cinfo; 315 316 *fck = ctx.fck; 317 *lck_div = ctx.dispc_cinfo.lck_div; 318 *pck_div = ctx.dispc_cinfo.pck_div; 319 320 return 0; 321} 322 323static int dpi_set_mode(struct dpi_data *dpi) 324{ 325 struct omap_dss_device *out = &dpi->output; 326 struct omap_overlay_manager *mgr = out->manager; 327 struct omap_video_timings *t = &dpi->timings; 328 int lck_div = 0, pck_div = 0; 329 unsigned long fck = 0; 330 unsigned long pck; 331 int r = 0; 332 333 if (dpi->pll) 334 r = dpi_set_dsi_clk(dpi, mgr->id, t->pixelclock, &fck, 335 &lck_div, &pck_div); 336 else 337 r = dpi_set_dispc_clk(dpi, t->pixelclock, &fck, 338 &lck_div, &pck_div); 339 if (r) 340 return r; 341 342 pck = fck / lck_div / pck_div; 343 344 if (pck != t->pixelclock) { 345 DSSWARN("Could not find exact pixel clock. Requested %d Hz, got %lu Hz\n", 346 t->pixelclock, pck); 347 348 t->pixelclock = pck; 349 } 350 351 dss_mgr_set_timings(mgr, t); 352 353 return 0; 354} 355 356static void dpi_config_lcd_manager(struct dpi_data *dpi) 357{ 358 struct omap_dss_device *out = &dpi->output; 359 struct omap_overlay_manager *mgr = out->manager; 360 361 dpi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; 362 363 dpi->mgr_config.stallmode = false; 364 dpi->mgr_config.fifohandcheck = false; 365 366 dpi->mgr_config.video_port_width = dpi->data_lines; 367 368 dpi->mgr_config.lcden_sig_polarity = 0; 369 370 dss_mgr_set_lcd_config(mgr, &dpi->mgr_config); 371} 372 373static int dpi_display_enable(struct omap_dss_device *dssdev) 374{ 375 struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev); 376 struct omap_dss_device *out = &dpi->output; 377 int r; 378 379 mutex_lock(&dpi->lock); 380 381 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && !dpi->vdds_dsi_reg) { 382 DSSERR("no VDSS_DSI regulator\n"); 383 r = -ENODEV; 384 goto err_no_reg; 385 } 386 387 if (out->manager == NULL) { 388 DSSERR("failed to enable display: no output/manager\n"); 389 r = -ENODEV; 390 goto err_no_out_mgr; 391 } 392 393 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) { 394 r = regulator_enable(dpi->vdds_dsi_reg); 395 if (r) 396 goto err_reg_enable; 397 } 398 399 r = dispc_runtime_get(); 400 if (r) 401 goto err_get_dispc; 402 403 r = dss_dpi_select_source(out->port_num, out->manager->id); 404 if (r) 405 goto err_src_sel; 406 407 if (dpi->pll) { 408 r = dss_pll_enable(dpi->pll); 409 if (r) 410 goto err_dsi_pll_init; 411 } 412 413 r = dpi_set_mode(dpi); 414 if (r) 415 goto err_set_mode; 416 417 dpi_config_lcd_manager(dpi); 418 419 mdelay(2); 420 421 r = dss_mgr_enable(out->manager); 422 if (r) 423 goto err_mgr_enable; 424 425 mutex_unlock(&dpi->lock); 426 427 return 0; 428 429err_mgr_enable: 430err_set_mode: 431 if (dpi->pll) 432 dss_pll_disable(dpi->pll); 433err_dsi_pll_init: 434err_src_sel: 435 dispc_runtime_put(); 436err_get_dispc: 437 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) 438 regulator_disable(dpi->vdds_dsi_reg); 439err_reg_enable: 440err_no_out_mgr: 441err_no_reg: 442 mutex_unlock(&dpi->lock); 443 return r; 444} 445 446static void dpi_display_disable(struct omap_dss_device *dssdev) 447{ 448 struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev); 449 struct omap_overlay_manager *mgr = dpi->output.manager; 450 451 mutex_lock(&dpi->lock); 452 453 dss_mgr_disable(mgr); 454 455 if (dpi->pll) { 456 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK); 457 dss_pll_disable(dpi->pll); 458 } 459 460 dispc_runtime_put(); 461 462 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) 463 regulator_disable(dpi->vdds_dsi_reg); 464 465 mutex_unlock(&dpi->lock); 466} 467 468static void dpi_set_timings(struct omap_dss_device *dssdev, 469 struct omap_video_timings *timings) 470{ 471 struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev); 472 473 DSSDBG("dpi_set_timings\n"); 474 475 mutex_lock(&dpi->lock); 476 477 dpi->timings = *timings; 478 479 mutex_unlock(&dpi->lock); 480} 481 482static void dpi_get_timings(struct omap_dss_device *dssdev, 483 struct omap_video_timings *timings) 484{ 485 struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev); 486 487 mutex_lock(&dpi->lock); 488 489 *timings = dpi->timings; 490 491 mutex_unlock(&dpi->lock); 492} 493 494static int dpi_check_timings(struct omap_dss_device *dssdev, 495 struct omap_video_timings *timings) 496{ 497 struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev); 498 struct omap_overlay_manager *mgr = dpi->output.manager; 499 int lck_div, pck_div; 500 unsigned long fck; 501 unsigned long pck; 502 struct dpi_clk_calc_ctx ctx; 503 bool ok; 504 505 if (mgr && !dispc_mgr_timings_ok(mgr->id, timings)) 506 return -EINVAL; 507 508 if (timings->pixelclock == 0) 509 return -EINVAL; 510 511 if (dpi->pll) { 512 ok = dpi_dsi_clk_calc(dpi, timings->pixelclock, &ctx); 513 if (!ok) 514 return -EINVAL; 515 516 fck = ctx.dsi_cinfo.clkout[HSDIV_DISPC]; 517 } else { 518 ok = dpi_dss_clk_calc(timings->pixelclock, &ctx); 519 if (!ok) 520 return -EINVAL; 521 522 fck = ctx.fck; 523 } 524 525 lck_div = ctx.dispc_cinfo.lck_div; 526 pck_div = ctx.dispc_cinfo.pck_div; 527 528 pck = fck / lck_div / pck_div; 529 530 timings->pixelclock = pck; 531 532 return 0; 533} 534 535static void dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines) 536{ 537 struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev); 538 539 mutex_lock(&dpi->lock); 540 541 dpi->data_lines = data_lines; 542 543 mutex_unlock(&dpi->lock); 544} 545 546static int dpi_verify_dsi_pll(struct dss_pll *pll) 547{ 548 int r; 549 550 /* do initial setup with the PLL to see if it is operational */ 551 552 r = dss_pll_enable(pll); 553 if (r) 554 return r; 555 556 dss_pll_disable(pll); 557 558 return 0; 559} 560 561static int dpi_init_regulator(struct dpi_data *dpi) 562{ 563 struct regulator *vdds_dsi; 564 565 if (!dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) 566 return 0; 567 568 if (dpi->vdds_dsi_reg) 569 return 0; 570 571 vdds_dsi = devm_regulator_get(&dpi->pdev->dev, "vdds_dsi"); 572 if (IS_ERR(vdds_dsi)) { 573 if (PTR_ERR(vdds_dsi) != -EPROBE_DEFER) 574 DSSERR("can't get VDDS_DSI regulator\n"); 575 return PTR_ERR(vdds_dsi); 576 } 577 578 dpi->vdds_dsi_reg = vdds_dsi; 579 580 return 0; 581} 582 583static void dpi_init_pll(struct dpi_data *dpi) 584{ 585 struct dss_pll *pll; 586 587 if (dpi->pll) 588 return; 589 590 pll = dpi_get_pll(dpi->output.dispc_channel); 591 if (!pll) 592 return; 593 594 /* On DRA7 we need to set a mux to use the PLL */ 595 if (omapdss_get_version() == OMAPDSS_VER_DRA7xx) 596 dss_ctrl_pll_set_control_mux(pll->id, dpi->output.dispc_channel); 597 598 if (dpi_verify_dsi_pll(pll)) { 599 DSSWARN("DSI PLL not operational\n"); 600 return; 601 } 602 603 dpi->pll = pll; 604} 605 606/* 607 * Return a hardcoded channel for the DPI output. This should work for 608 * current use cases, but this can be later expanded to either resolve 609 * the channel in some more dynamic manner, or get the channel as a user 610 * parameter. 611 */ 612static enum omap_channel dpi_get_channel(int port_num) 613{ 614 switch (omapdss_get_version()) { 615 case OMAPDSS_VER_OMAP24xx: 616 case OMAPDSS_VER_OMAP34xx_ES1: 617 case OMAPDSS_VER_OMAP34xx_ES3: 618 case OMAPDSS_VER_OMAP3630: 619 case OMAPDSS_VER_AM35xx: 620 case OMAPDSS_VER_AM43xx: 621 return OMAP_DSS_CHANNEL_LCD; 622 623 case OMAPDSS_VER_DRA7xx: 624 switch (port_num) { 625 case 2: 626 return OMAP_DSS_CHANNEL_LCD3; 627 case 1: 628 return OMAP_DSS_CHANNEL_LCD2; 629 case 0: 630 default: 631 return OMAP_DSS_CHANNEL_LCD; 632 } 633 634 case OMAPDSS_VER_OMAP4430_ES1: 635 case OMAPDSS_VER_OMAP4430_ES2: 636 case OMAPDSS_VER_OMAP4: 637 return OMAP_DSS_CHANNEL_LCD2; 638 639 case OMAPDSS_VER_OMAP5: 640 return OMAP_DSS_CHANNEL_LCD3; 641 642 default: 643 DSSWARN("unsupported DSS version\n"); 644 return OMAP_DSS_CHANNEL_LCD; 645 } 646} 647 648static int dpi_connect(struct omap_dss_device *dssdev, 649 struct omap_dss_device *dst) 650{ 651 struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev); 652 struct omap_overlay_manager *mgr; 653 int r; 654 655 r = dpi_init_regulator(dpi); 656 if (r) 657 return r; 658 659 dpi_init_pll(dpi); 660 661 mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel); 662 if (!mgr) 663 return -ENODEV; 664 665 r = dss_mgr_connect(mgr, dssdev); 666 if (r) 667 return r; 668 669 r = omapdss_output_set_device(dssdev, dst); 670 if (r) { 671 DSSERR("failed to connect output to new device: %s\n", 672 dst->name); 673 dss_mgr_disconnect(mgr, dssdev); 674 return r; 675 } 676 677 return 0; 678} 679 680static void dpi_disconnect(struct omap_dss_device *dssdev, 681 struct omap_dss_device *dst) 682{ 683 WARN_ON(dst != dssdev->dst); 684 685 if (dst != dssdev->dst) 686 return; 687 688 omapdss_output_unset_device(dssdev); 689 690 if (dssdev->manager) 691 dss_mgr_disconnect(dssdev->manager, dssdev); 692} 693 694static const struct omapdss_dpi_ops dpi_ops = { 695 .connect = dpi_connect, 696 .disconnect = dpi_disconnect, 697 698 .enable = dpi_display_enable, 699 .disable = dpi_display_disable, 700 701 .check_timings = dpi_check_timings, 702 .set_timings = dpi_set_timings, 703 .get_timings = dpi_get_timings, 704 705 .set_data_lines = dpi_set_data_lines, 706}; 707 708static void dpi_init_output(struct platform_device *pdev) 709{ 710 struct dpi_data *dpi = dpi_get_data_from_pdev(pdev); 711 struct omap_dss_device *out = &dpi->output; 712 713 out->dev = &pdev->dev; 714 out->id = OMAP_DSS_OUTPUT_DPI; 715 out->output_type = OMAP_DISPLAY_TYPE_DPI; 716 out->name = "dpi.0"; 717 out->dispc_channel = dpi_get_channel(0); 718 out->ops.dpi = &dpi_ops; 719 out->owner = THIS_MODULE; 720 721 omapdss_register_output(out); 722} 723 724static void dpi_uninit_output(struct platform_device *pdev) 725{ 726 struct dpi_data *dpi = dpi_get_data_from_pdev(pdev); 727 struct omap_dss_device *out = &dpi->output; 728 729 omapdss_unregister_output(out); 730} 731 732static void dpi_init_output_port(struct platform_device *pdev, 733 struct device_node *port) 734{ 735 struct dpi_data *dpi = port->data; 736 struct omap_dss_device *out = &dpi->output; 737 int r; 738 u32 port_num; 739 740 r = of_property_read_u32(port, "reg", &port_num); 741 if (r) 742 port_num = 0; 743 744 switch (port_num) { 745 case 2: 746 out->name = "dpi.2"; 747 break; 748 case 1: 749 out->name = "dpi.1"; 750 break; 751 case 0: 752 default: 753 out->name = "dpi.0"; 754 break; 755 } 756 757 out->dev = &pdev->dev; 758 out->id = OMAP_DSS_OUTPUT_DPI; 759 out->output_type = OMAP_DISPLAY_TYPE_DPI; 760 out->dispc_channel = dpi_get_channel(port_num); 761 out->port_num = port_num; 762 out->ops.dpi = &dpi_ops; 763 out->owner = THIS_MODULE; 764 765 omapdss_register_output(out); 766} 767 768static void dpi_uninit_output_port(struct device_node *port) 769{ 770 struct dpi_data *dpi = port->data; 771 struct omap_dss_device *out = &dpi->output; 772 773 omapdss_unregister_output(out); 774} 775 776static int dpi_bind(struct device *dev, struct device *master, void *data) 777{ 778 struct platform_device *pdev = to_platform_device(dev); 779 struct dpi_data *dpi; 780 781 dpi = devm_kzalloc(&pdev->dev, sizeof(*dpi), GFP_KERNEL); 782 if (!dpi) 783 return -ENOMEM; 784 785 dpi->pdev = pdev; 786 787 platform_set_drvdata(pdev, dpi); 788 789 mutex_init(&dpi->lock); 790 791 dpi_init_output(pdev); 792 793 return 0; 794} 795 796static void dpi_unbind(struct device *dev, struct device *master, void *data) 797{ 798 struct platform_device *pdev = to_platform_device(dev); 799 800 dpi_uninit_output(pdev); 801} 802 803static const struct component_ops dpi_component_ops = { 804 .bind = dpi_bind, 805 .unbind = dpi_unbind, 806}; 807 808static int dpi_probe(struct platform_device *pdev) 809{ 810 return component_add(&pdev->dev, &dpi_component_ops); 811} 812 813static int dpi_remove(struct platform_device *pdev) 814{ 815 component_del(&pdev->dev, &dpi_component_ops); 816 return 0; 817} 818 819static struct platform_driver omap_dpi_driver = { 820 .probe = dpi_probe, 821 .remove = dpi_remove, 822 .driver = { 823 .name = "omapdss_dpi", 824 .suppress_bind_attrs = true, 825 }, 826}; 827 828int __init dpi_init_platform_driver(void) 829{ 830 return platform_driver_register(&omap_dpi_driver); 831} 832 833void dpi_uninit_platform_driver(void) 834{ 835 platform_driver_unregister(&omap_dpi_driver); 836} 837 838int dpi_init_port(struct platform_device *pdev, struct device_node *port) 839{ 840 struct dpi_data *dpi; 841 struct device_node *ep; 842 u32 datalines; 843 int r; 844 845 dpi = devm_kzalloc(&pdev->dev, sizeof(*dpi), GFP_KERNEL); 846 if (!dpi) 847 return -ENOMEM; 848 849 ep = omapdss_of_get_next_endpoint(port, NULL); 850 if (!ep) 851 return 0; 852 853 r = of_property_read_u32(ep, "data-lines", &datalines); 854 if (r) { 855 DSSERR("failed to parse datalines\n"); 856 goto err_datalines; 857 } 858 859 dpi->data_lines = datalines; 860 861 of_node_put(ep); 862 863 dpi->pdev = pdev; 864 port->data = dpi; 865 866 mutex_init(&dpi->lock); 867 868 dpi_init_output_port(pdev, port); 869 870 dpi->port_initialized = true; 871 872 return 0; 873 874err_datalines: 875 of_node_put(ep); 876 877 return r; 878} 879 880void dpi_uninit_port(struct device_node *port) 881{ 882 struct dpi_data *dpi = port->data; 883 884 if (!dpi->port_initialized) 885 return; 886 887 dpi_uninit_output_port(port); 888}