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