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