| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2009 Nokia Corporation |
|---|
| 3 | 4 | * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> |
|---|
| 4 | | - * |
|---|
| 5 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 6 | | - * under the terms of the GNU General Public License version 2 as published by |
|---|
| 7 | | - * the Free Software Foundation. |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is distributed in the hope that it will be useful, but WITHOUT |
|---|
| 10 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|---|
| 11 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
|---|
| 12 | | - * more details. |
|---|
| 13 | | - * |
|---|
| 14 | | - * You should have received a copy of the GNU General Public License along with |
|---|
| 15 | | - * this program. If not, see <http://www.gnu.org/licenses/>. |
|---|
| 16 | 5 | */ |
|---|
| 17 | 6 | |
|---|
| 18 | 7 | #define DSS_SUBSYS_NAME "DSI" |
|---|
| .. | .. |
|---|
| 403 | 392 | struct { |
|---|
| 404 | 393 | struct dss_debugfs_entry *irqs; |
|---|
| 405 | 394 | struct dss_debugfs_entry *regs; |
|---|
| 395 | + struct dss_debugfs_entry *clks; |
|---|
| 406 | 396 | } debugfs; |
|---|
| 407 | 397 | |
|---|
| 408 | 398 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS |
|---|
| .. | .. |
|---|
| 440 | 430 | static inline struct dsi_data *to_dsi_data(struct omap_dss_device *dssdev) |
|---|
| 441 | 431 | { |
|---|
| 442 | 432 | return dev_get_drvdata(dssdev->dev); |
|---|
| 443 | | -} |
|---|
| 444 | | - |
|---|
| 445 | | -static struct dsi_data *dsi_get_dsi_from_id(int module) |
|---|
| 446 | | -{ |
|---|
| 447 | | - struct omap_dss_device *out; |
|---|
| 448 | | - enum omap_dss_output_id id; |
|---|
| 449 | | - |
|---|
| 450 | | - switch (module) { |
|---|
| 451 | | - case 0: |
|---|
| 452 | | - id = OMAP_DSS_OUTPUT_DSI1; |
|---|
| 453 | | - break; |
|---|
| 454 | | - case 1: |
|---|
| 455 | | - id = OMAP_DSS_OUTPUT_DSI2; |
|---|
| 456 | | - break; |
|---|
| 457 | | - default: |
|---|
| 458 | | - return NULL; |
|---|
| 459 | | - } |
|---|
| 460 | | - |
|---|
| 461 | | - out = omap_dss_get_output(id); |
|---|
| 462 | | - |
|---|
| 463 | | - return out ? to_dsi_data(out) : NULL; |
|---|
| 464 | 433 | } |
|---|
| 465 | 434 | |
|---|
| 466 | 435 | static inline void dsi_write_reg(struct dsi_data *dsi, |
|---|
| .. | .. |
|---|
| 1157 | 1126 | WARN_ON(r < 0 && r != -ENOSYS); |
|---|
| 1158 | 1127 | } |
|---|
| 1159 | 1128 | |
|---|
| 1160 | | -static int dsi_regulator_init(struct dsi_data *dsi) |
|---|
| 1161 | | -{ |
|---|
| 1162 | | - struct regulator *vdds_dsi; |
|---|
| 1163 | | - |
|---|
| 1164 | | - if (dsi->vdds_dsi_reg != NULL) |
|---|
| 1165 | | - return 0; |
|---|
| 1166 | | - |
|---|
| 1167 | | - vdds_dsi = devm_regulator_get(dsi->dev, "vdd"); |
|---|
| 1168 | | - |
|---|
| 1169 | | - if (IS_ERR(vdds_dsi)) { |
|---|
| 1170 | | - if (PTR_ERR(vdds_dsi) != -EPROBE_DEFER) |
|---|
| 1171 | | - DSSERR("can't get DSI VDD regulator\n"); |
|---|
| 1172 | | - return PTR_ERR(vdds_dsi); |
|---|
| 1173 | | - } |
|---|
| 1174 | | - |
|---|
| 1175 | | - dsi->vdds_dsi_reg = vdds_dsi; |
|---|
| 1176 | | - |
|---|
| 1177 | | - return 0; |
|---|
| 1178 | | -} |
|---|
| 1179 | | - |
|---|
| 1180 | 1129 | static void _dsi_print_reset_status(struct dsi_data *dsi) |
|---|
| 1181 | 1130 | { |
|---|
| 1182 | 1131 | u32 l; |
|---|
| .. | .. |
|---|
| 1373 | 1322 | |
|---|
| 1374 | 1323 | DSSDBG("PLL init\n"); |
|---|
| 1375 | 1324 | |
|---|
| 1376 | | - r = dsi_regulator_init(dsi); |
|---|
| 1377 | | - if (r) |
|---|
| 1378 | | - return r; |
|---|
| 1379 | | - |
|---|
| 1380 | 1325 | r = dsi_runtime_get(dsi); |
|---|
| 1381 | 1326 | if (r) |
|---|
| 1382 | 1327 | return r; |
|---|
| .. | .. |
|---|
| 1434 | 1379 | DSSDBG("PLL disable done\n"); |
|---|
| 1435 | 1380 | } |
|---|
| 1436 | 1381 | |
|---|
| 1437 | | -static void dsi_dump_dsi_clocks(struct dsi_data *dsi, struct seq_file *s) |
|---|
| 1382 | +static int dsi_dump_dsi_clocks(struct seq_file *s, void *p) |
|---|
| 1438 | 1383 | { |
|---|
| 1384 | + struct dsi_data *dsi = s->private; |
|---|
| 1439 | 1385 | struct dss_pll_clock_info *cinfo = &dsi->pll.cinfo; |
|---|
| 1440 | 1386 | enum dss_clk_source dispc_clk_src, dsi_clk_src; |
|---|
| 1441 | 1387 | int dsi_module = dsi->module_id; |
|---|
| .. | .. |
|---|
| 1445 | 1391 | dsi_clk_src = dss_get_dsi_clk_source(dsi->dss, dsi_module); |
|---|
| 1446 | 1392 | |
|---|
| 1447 | 1393 | if (dsi_runtime_get(dsi)) |
|---|
| 1448 | | - return; |
|---|
| 1394 | + return 0; |
|---|
| 1449 | 1395 | |
|---|
| 1450 | 1396 | seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1); |
|---|
| 1451 | 1397 | |
|---|
| .. | .. |
|---|
| 1489 | 1435 | seq_printf(s, "LP_CLK\t\t%lu\n", dsi->current_lp_cinfo.lp_clk); |
|---|
| 1490 | 1436 | |
|---|
| 1491 | 1437 | dsi_runtime_put(dsi); |
|---|
| 1492 | | -} |
|---|
| 1493 | 1438 | |
|---|
| 1494 | | -void dsi_dump_clocks(struct seq_file *s) |
|---|
| 1495 | | -{ |
|---|
| 1496 | | - struct dsi_data *dsi; |
|---|
| 1497 | | - int i; |
|---|
| 1498 | | - |
|---|
| 1499 | | - for (i = 0; i < MAX_NUM_DSI; i++) { |
|---|
| 1500 | | - dsi = dsi_get_dsi_from_id(i); |
|---|
| 1501 | | - if (dsi) |
|---|
| 1502 | | - dsi_dump_dsi_clocks(dsi, s); |
|---|
| 1503 | | - } |
|---|
| 1439 | + return 0; |
|---|
| 1504 | 1440 | } |
|---|
| 1505 | 1441 | |
|---|
| 1506 | 1442 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS |
|---|
| 1507 | | -static void dsi_dump_dsi_irqs(struct dsi_data *dsi, struct seq_file *s) |
|---|
| 1443 | +static int dsi_dump_dsi_irqs(struct seq_file *s, void *p) |
|---|
| 1508 | 1444 | { |
|---|
| 1445 | + struct dsi_data *dsi = s->private; |
|---|
| 1509 | 1446 | unsigned long flags; |
|---|
| 1510 | | - struct dsi_irq_stats stats; |
|---|
| 1447 | + struct dsi_irq_stats *stats; |
|---|
| 1448 | + |
|---|
| 1449 | + stats = kmalloc(sizeof(*stats), GFP_KERNEL); |
|---|
| 1450 | + if (!stats) |
|---|
| 1451 | + return -ENOMEM; |
|---|
| 1511 | 1452 | |
|---|
| 1512 | 1453 | spin_lock_irqsave(&dsi->irq_stats_lock, flags); |
|---|
| 1513 | 1454 | |
|---|
| 1514 | | - stats = dsi->irq_stats; |
|---|
| 1455 | + *stats = dsi->irq_stats; |
|---|
| 1515 | 1456 | memset(&dsi->irq_stats, 0, sizeof(dsi->irq_stats)); |
|---|
| 1516 | 1457 | dsi->irq_stats.last_reset = jiffies; |
|---|
| 1517 | 1458 | |
|---|
| 1518 | 1459 | spin_unlock_irqrestore(&dsi->irq_stats_lock, flags); |
|---|
| 1519 | 1460 | |
|---|
| 1520 | 1461 | seq_printf(s, "period %u ms\n", |
|---|
| 1521 | | - jiffies_to_msecs(jiffies - stats.last_reset)); |
|---|
| 1462 | + jiffies_to_msecs(jiffies - stats->last_reset)); |
|---|
| 1522 | 1463 | |
|---|
| 1523 | | - seq_printf(s, "irqs %d\n", stats.irq_count); |
|---|
| 1464 | + seq_printf(s, "irqs %d\n", stats->irq_count); |
|---|
| 1524 | 1465 | #define PIS(x) \ |
|---|
| 1525 | | - seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]); |
|---|
| 1466 | + seq_printf(s, "%-20s %10d\n", #x, stats->dsi_irqs[ffs(DSI_IRQ_##x)-1]); |
|---|
| 1526 | 1467 | |
|---|
| 1527 | 1468 | seq_printf(s, "-- DSI%d interrupts --\n", dsi->module_id + 1); |
|---|
| 1528 | 1469 | PIS(VC0); |
|---|
| .. | .. |
|---|
| 1546 | 1487 | |
|---|
| 1547 | 1488 | #define PIS(x) \ |
|---|
| 1548 | 1489 | seq_printf(s, "%-20s %10d %10d %10d %10d\n", #x, \ |
|---|
| 1549 | | - stats.vc_irqs[0][ffs(DSI_VC_IRQ_##x)-1], \ |
|---|
| 1550 | | - stats.vc_irqs[1][ffs(DSI_VC_IRQ_##x)-1], \ |
|---|
| 1551 | | - stats.vc_irqs[2][ffs(DSI_VC_IRQ_##x)-1], \ |
|---|
| 1552 | | - stats.vc_irqs[3][ffs(DSI_VC_IRQ_##x)-1]); |
|---|
| 1490 | + stats->vc_irqs[0][ffs(DSI_VC_IRQ_##x)-1], \ |
|---|
| 1491 | + stats->vc_irqs[1][ffs(DSI_VC_IRQ_##x)-1], \ |
|---|
| 1492 | + stats->vc_irqs[2][ffs(DSI_VC_IRQ_##x)-1], \ |
|---|
| 1493 | + stats->vc_irqs[3][ffs(DSI_VC_IRQ_##x)-1]); |
|---|
| 1553 | 1494 | |
|---|
| 1554 | 1495 | seq_printf(s, "-- VC interrupts --\n"); |
|---|
| 1555 | 1496 | PIS(CS); |
|---|
| .. | .. |
|---|
| 1565 | 1506 | |
|---|
| 1566 | 1507 | #define PIS(x) \ |
|---|
| 1567 | 1508 | seq_printf(s, "%-20s %10d\n", #x, \ |
|---|
| 1568 | | - stats.cio_irqs[ffs(DSI_CIO_IRQ_##x)-1]); |
|---|
| 1509 | + stats->cio_irqs[ffs(DSI_CIO_IRQ_##x)-1]); |
|---|
| 1569 | 1510 | |
|---|
| 1570 | 1511 | seq_printf(s, "-- CIO interrupts --\n"); |
|---|
| 1571 | 1512 | PIS(ERRSYNCESC1); |
|---|
| .. | .. |
|---|
| 1589 | 1530 | PIS(ULPSACTIVENOT_ALL0); |
|---|
| 1590 | 1531 | PIS(ULPSACTIVENOT_ALL1); |
|---|
| 1591 | 1532 | #undef PIS |
|---|
| 1592 | | -} |
|---|
| 1593 | 1533 | |
|---|
| 1594 | | -static int dsi1_dump_irqs(struct seq_file *s, void *p) |
|---|
| 1595 | | -{ |
|---|
| 1596 | | - struct dsi_data *dsi = dsi_get_dsi_from_id(0); |
|---|
| 1534 | + kfree(stats); |
|---|
| 1597 | 1535 | |
|---|
| 1598 | | - dsi_dump_dsi_irqs(dsi, s); |
|---|
| 1599 | | - return 0; |
|---|
| 1600 | | -} |
|---|
| 1601 | | - |
|---|
| 1602 | | -static int dsi2_dump_irqs(struct seq_file *s, void *p) |
|---|
| 1603 | | -{ |
|---|
| 1604 | | - struct dsi_data *dsi = dsi_get_dsi_from_id(1); |
|---|
| 1605 | | - |
|---|
| 1606 | | - dsi_dump_dsi_irqs(dsi, s); |
|---|
| 1607 | 1536 | return 0; |
|---|
| 1608 | 1537 | } |
|---|
| 1609 | 1538 | #endif |
|---|
| 1610 | 1539 | |
|---|
| 1611 | | -static void dsi_dump_dsi_regs(struct dsi_data *dsi, struct seq_file *s) |
|---|
| 1540 | +static int dsi_dump_dsi_regs(struct seq_file *s, void *p) |
|---|
| 1612 | 1541 | { |
|---|
| 1613 | | -#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsi, r)) |
|---|
| 1542 | + struct dsi_data *dsi = s->private; |
|---|
| 1614 | 1543 | |
|---|
| 1615 | 1544 | if (dsi_runtime_get(dsi)) |
|---|
| 1616 | | - return; |
|---|
| 1545 | + return 0; |
|---|
| 1617 | 1546 | dsi_enable_scp_clk(dsi); |
|---|
| 1618 | 1547 | |
|---|
| 1548 | +#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsi, r)) |
|---|
| 1619 | 1549 | DUMPREG(DSI_REVISION); |
|---|
| 1620 | 1550 | DUMPREG(DSI_SYSCONFIG); |
|---|
| 1621 | 1551 | DUMPREG(DSI_SYSSTATUS); |
|---|
| .. | .. |
|---|
| 1685 | 1615 | DUMPREG(DSI_PLL_GO); |
|---|
| 1686 | 1616 | DUMPREG(DSI_PLL_CONFIGURATION1); |
|---|
| 1687 | 1617 | DUMPREG(DSI_PLL_CONFIGURATION2); |
|---|
| 1618 | +#undef DUMPREG |
|---|
| 1688 | 1619 | |
|---|
| 1689 | 1620 | dsi_disable_scp_clk(dsi); |
|---|
| 1690 | 1621 | dsi_runtime_put(dsi); |
|---|
| 1691 | | -#undef DUMPREG |
|---|
| 1692 | | -} |
|---|
| 1693 | 1622 | |
|---|
| 1694 | | -static int dsi1_dump_regs(struct seq_file *s, void *p) |
|---|
| 1695 | | -{ |
|---|
| 1696 | | - struct dsi_data *dsi = dsi_get_dsi_from_id(0); |
|---|
| 1697 | | - |
|---|
| 1698 | | - dsi_dump_dsi_regs(dsi, s); |
|---|
| 1699 | | - return 0; |
|---|
| 1700 | | -} |
|---|
| 1701 | | - |
|---|
| 1702 | | -static int dsi2_dump_regs(struct seq_file *s, void *p) |
|---|
| 1703 | | -{ |
|---|
| 1704 | | - struct dsi_data *dsi = dsi_get_dsi_from_id(1); |
|---|
| 1705 | | - |
|---|
| 1706 | | - dsi_dump_dsi_regs(dsi, s); |
|---|
| 1707 | 1623 | return 0; |
|---|
| 1708 | 1624 | } |
|---|
| 1709 | 1625 | |
|---|
| .. | .. |
|---|
| 3330 | 3246 | |
|---|
| 3331 | 3247 | if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { |
|---|
| 3332 | 3248 | int bpp = dsi_get_pixel_size(dsi->pix_fmt); |
|---|
| 3333 | | - struct videomode *vm = &dsi->vm; |
|---|
| 3249 | + const struct videomode *vm = &dsi->vm; |
|---|
| 3334 | 3250 | /* |
|---|
| 3335 | 3251 | * Don't use line buffers if width is greater than the video |
|---|
| 3336 | 3252 | * port's line buffer size |
|---|
| .. | .. |
|---|
| 3459 | 3375 | int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat; |
|---|
| 3460 | 3376 | int tclk_trail, ths_exit, exiths_clk; |
|---|
| 3461 | 3377 | bool ddr_alwon; |
|---|
| 3462 | | - struct videomode *vm = &dsi->vm; |
|---|
| 3378 | + const struct videomode *vm = &dsi->vm; |
|---|
| 3463 | 3379 | int bpp = dsi_get_pixel_size(dsi->pix_fmt); |
|---|
| 3464 | 3380 | int ndl = dsi->num_lanes_used - 1; |
|---|
| 3465 | 3381 | int dsi_fclk_hsdiv = dsi->user_dsi_cinfo.mX[HSDIV_DSI] + 1; |
|---|
| .. | .. |
|---|
| 3638 | 3554 | |
|---|
| 3639 | 3555 | static void dsi_proto_timings(struct dsi_data *dsi) |
|---|
| 3640 | 3556 | { |
|---|
| 3641 | | - unsigned int tlpx, tclk_zero, tclk_prepare, tclk_trail; |
|---|
| 3557 | + unsigned int tlpx, tclk_zero, tclk_prepare; |
|---|
| 3642 | 3558 | unsigned int tclk_pre, tclk_post; |
|---|
| 3643 | 3559 | unsigned int ths_prepare, ths_prepare_ths_zero, ths_zero; |
|---|
| 3644 | 3560 | unsigned int ths_trail, ths_exit; |
|---|
| .. | .. |
|---|
| 3657 | 3573 | |
|---|
| 3658 | 3574 | r = dsi_read_reg(dsi, DSI_DSIPHY_CFG1); |
|---|
| 3659 | 3575 | tlpx = FLD_GET(r, 20, 16) * 2; |
|---|
| 3660 | | - tclk_trail = FLD_GET(r, 15, 8); |
|---|
| 3661 | 3576 | tclk_zero = FLD_GET(r, 7, 0); |
|---|
| 3662 | 3577 | |
|---|
| 3663 | 3578 | r = dsi_read_reg(dsi, DSI_DSIPHY_CFG2); |
|---|
| .. | .. |
|---|
| 3709 | 3624 | int vbp = dsi->vm_timings.vbp; |
|---|
| 3710 | 3625 | int window_sync = dsi->vm_timings.window_sync; |
|---|
| 3711 | 3626 | bool hsync_end; |
|---|
| 3712 | | - struct videomode *vm = &dsi->vm; |
|---|
| 3627 | + const struct videomode *vm = &dsi->vm; |
|---|
| 3713 | 3628 | int bpp = dsi_get_pixel_size(dsi->pix_fmt); |
|---|
| 3714 | 3629 | int tl, t_he, width_bytes; |
|---|
| 3715 | 3630 | |
|---|
| .. | .. |
|---|
| 3818 | 3733 | { |
|---|
| 3819 | 3734 | struct dsi_data *dsi = to_dsi_data(dssdev); |
|---|
| 3820 | 3735 | int bpp = dsi_get_pixel_size(dsi->pix_fmt); |
|---|
| 3821 | | - struct omap_dss_device *out = &dsi->output; |
|---|
| 3822 | 3736 | u8 data_type; |
|---|
| 3823 | 3737 | u16 word_count; |
|---|
| 3824 | 3738 | int r; |
|---|
| 3825 | 3739 | |
|---|
| 3826 | | - if (!out->dispc_channel_connected) { |
|---|
| 3827 | | - DSSERR("failed to enable display: no output/manager\n"); |
|---|
| 3828 | | - return -ENODEV; |
|---|
| 3829 | | - } |
|---|
| 3830 | | - |
|---|
| 3831 | 3740 | r = dsi_display_init_dispc(dsi); |
|---|
| 3832 | 3741 | if (r) |
|---|
| 3833 | | - goto err_init_dispc; |
|---|
| 3742 | + return r; |
|---|
| 3834 | 3743 | |
|---|
| 3835 | 3744 | if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { |
|---|
| 3836 | 3745 | switch (dsi->pix_fmt) { |
|---|
| .. | .. |
|---|
| 3879 | 3788 | } |
|---|
| 3880 | 3789 | err_pix_fmt: |
|---|
| 3881 | 3790 | dsi_display_uninit_dispc(dsi); |
|---|
| 3882 | | -err_init_dispc: |
|---|
| 3883 | 3791 | return r; |
|---|
| 3884 | 3792 | } |
|---|
| 3885 | 3793 | |
|---|
| .. | .. |
|---|
| 3965 | 3873 | r = schedule_delayed_work(&dsi->framedone_timeout_work, |
|---|
| 3966 | 3874 | msecs_to_jiffies(250)); |
|---|
| 3967 | 3875 | BUG_ON(r == 0); |
|---|
| 3968 | | - |
|---|
| 3969 | | - dss_mgr_set_timings(&dsi->output, &dsi->vm); |
|---|
| 3970 | 3876 | |
|---|
| 3971 | 3877 | dss_mgr_start_update(&dsi->output); |
|---|
| 3972 | 3878 | |
|---|
| .. | .. |
|---|
| 4109 | 4015 | dsi->mgr_config.fifohandcheck = false; |
|---|
| 4110 | 4016 | } |
|---|
| 4111 | 4017 | |
|---|
| 4112 | | - /* |
|---|
| 4113 | | - * override interlace, logic level and edge related parameters in |
|---|
| 4114 | | - * videomode with default values |
|---|
| 4115 | | - */ |
|---|
| 4116 | | - dsi->vm.flags &= ~DISPLAY_FLAGS_INTERLACED; |
|---|
| 4117 | | - dsi->vm.flags &= ~DISPLAY_FLAGS_HSYNC_LOW; |
|---|
| 4118 | | - dsi->vm.flags |= DISPLAY_FLAGS_HSYNC_HIGH; |
|---|
| 4119 | | - dsi->vm.flags &= ~DISPLAY_FLAGS_VSYNC_LOW; |
|---|
| 4120 | | - dsi->vm.flags |= DISPLAY_FLAGS_VSYNC_HIGH; |
|---|
| 4121 | | - dsi->vm.flags &= ~DISPLAY_FLAGS_PIXDATA_NEGEDGE; |
|---|
| 4122 | | - dsi->vm.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE; |
|---|
| 4123 | | - dsi->vm.flags &= ~DISPLAY_FLAGS_DE_LOW; |
|---|
| 4124 | | - dsi->vm.flags |= DISPLAY_FLAGS_DE_HIGH; |
|---|
| 4125 | | - dsi->vm.flags &= ~DISPLAY_FLAGS_SYNC_POSEDGE; |
|---|
| 4126 | | - dsi->vm.flags |= DISPLAY_FLAGS_SYNC_NEGEDGE; |
|---|
| 4127 | | - |
|---|
| 4128 | | - dss_mgr_set_timings(&dsi->output, &dsi->vm); |
|---|
| 4129 | | - |
|---|
| 4130 | 4018 | r = dsi_configure_dispc_clocks(dsi); |
|---|
| 4131 | 4019 | if (r) |
|---|
| 4132 | 4020 | goto err1; |
|---|
| .. | .. |
|---|
| 4262 | 4150 | } |
|---|
| 4263 | 4151 | } |
|---|
| 4264 | 4152 | |
|---|
| 4265 | | -static int dsi_display_enable(struct omap_dss_device *dssdev) |
|---|
| 4153 | +static void dsi_display_enable(struct omap_dss_device *dssdev) |
|---|
| 4266 | 4154 | { |
|---|
| 4267 | 4155 | struct dsi_data *dsi = to_dsi_data(dssdev); |
|---|
| 4268 | | - int r = 0; |
|---|
| 4156 | + int r; |
|---|
| 4269 | 4157 | |
|---|
| 4270 | 4158 | DSSDBG("dsi_display_enable\n"); |
|---|
| 4271 | 4159 | |
|---|
| .. | .. |
|---|
| 4285 | 4173 | |
|---|
| 4286 | 4174 | mutex_unlock(&dsi->lock); |
|---|
| 4287 | 4175 | |
|---|
| 4288 | | - return 0; |
|---|
| 4176 | + return; |
|---|
| 4289 | 4177 | |
|---|
| 4290 | 4178 | err_init_dsi: |
|---|
| 4291 | 4179 | dsi_runtime_put(dsi); |
|---|
| 4292 | 4180 | err_get_dsi: |
|---|
| 4293 | 4181 | mutex_unlock(&dsi->lock); |
|---|
| 4294 | 4182 | DSSDBG("dsi_display_enable FAILED\n"); |
|---|
| 4295 | | - return r; |
|---|
| 4296 | 4183 | } |
|---|
| 4297 | 4184 | |
|---|
| 4298 | 4185 | static void dsi_display_disable(struct omap_dss_device *dssdev, |
|---|
| .. | .. |
|---|
| 4842 | 4729 | dsi->user_dispc_cinfo = ctx.dispc_cinfo; |
|---|
| 4843 | 4730 | |
|---|
| 4844 | 4731 | dsi->vm = ctx.vm; |
|---|
| 4732 | + |
|---|
| 4733 | + /* |
|---|
| 4734 | + * override interlace, logic level and edge related parameters in |
|---|
| 4735 | + * videomode with default values |
|---|
| 4736 | + */ |
|---|
| 4737 | + dsi->vm.flags &= ~DISPLAY_FLAGS_INTERLACED; |
|---|
| 4738 | + dsi->vm.flags &= ~DISPLAY_FLAGS_HSYNC_LOW; |
|---|
| 4739 | + dsi->vm.flags |= DISPLAY_FLAGS_HSYNC_HIGH; |
|---|
| 4740 | + dsi->vm.flags &= ~DISPLAY_FLAGS_VSYNC_LOW; |
|---|
| 4741 | + dsi->vm.flags |= DISPLAY_FLAGS_VSYNC_HIGH; |
|---|
| 4742 | + /* |
|---|
| 4743 | + * HACK: These flags should be handled through the omap_dss_device bus |
|---|
| 4744 | + * flags, but this will only be possible when the DSI encoder will be |
|---|
| 4745 | + * converted to the omapdrm-managed encoder model. |
|---|
| 4746 | + */ |
|---|
| 4747 | + dsi->vm.flags &= ~DISPLAY_FLAGS_PIXDATA_NEGEDGE; |
|---|
| 4748 | + dsi->vm.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE; |
|---|
| 4749 | + dsi->vm.flags &= ~DISPLAY_FLAGS_DE_LOW; |
|---|
| 4750 | + dsi->vm.flags |= DISPLAY_FLAGS_DE_HIGH; |
|---|
| 4751 | + dsi->vm.flags &= ~DISPLAY_FLAGS_SYNC_POSEDGE; |
|---|
| 4752 | + dsi->vm.flags |= DISPLAY_FLAGS_SYNC_NEGEDGE; |
|---|
| 4753 | + |
|---|
| 4754 | + dss_mgr_set_timings(&dsi->output, &dsi->vm); |
|---|
| 4755 | + |
|---|
| 4845 | 4756 | dsi->vm_timings = ctx.dsi_vm; |
|---|
| 4846 | 4757 | |
|---|
| 4847 | 4758 | mutex_unlock(&dsi->lock); |
|---|
| .. | .. |
|---|
| 4962 | 4873 | return 0; |
|---|
| 4963 | 4874 | } |
|---|
| 4964 | 4875 | |
|---|
| 4965 | | -static int dsi_connect(struct omap_dss_device *dssdev, |
|---|
| 4966 | | - struct omap_dss_device *dst) |
|---|
| 4876 | +static int dsi_connect(struct omap_dss_device *src, |
|---|
| 4877 | + struct omap_dss_device *dst) |
|---|
| 4967 | 4878 | { |
|---|
| 4968 | | - struct dsi_data *dsi = to_dsi_data(dssdev); |
|---|
| 4969 | | - int r; |
|---|
| 4970 | | - |
|---|
| 4971 | | - r = dsi_regulator_init(dsi); |
|---|
| 4972 | | - if (r) |
|---|
| 4973 | | - return r; |
|---|
| 4974 | | - |
|---|
| 4975 | | - r = dss_mgr_connect(&dsi->output, dssdev); |
|---|
| 4976 | | - if (r) |
|---|
| 4977 | | - return r; |
|---|
| 4978 | | - |
|---|
| 4979 | | - r = omapdss_output_set_device(dssdev, dst); |
|---|
| 4980 | | - if (r) { |
|---|
| 4981 | | - DSSERR("failed to connect output to new device: %s\n", |
|---|
| 4982 | | - dssdev->name); |
|---|
| 4983 | | - dss_mgr_disconnect(&dsi->output, dssdev); |
|---|
| 4984 | | - return r; |
|---|
| 4985 | | - } |
|---|
| 4986 | | - |
|---|
| 4987 | | - return 0; |
|---|
| 4879 | + return omapdss_device_connect(dst->dss, dst, dst->next); |
|---|
| 4988 | 4880 | } |
|---|
| 4989 | 4881 | |
|---|
| 4990 | | -static void dsi_disconnect(struct omap_dss_device *dssdev, |
|---|
| 4991 | | - struct omap_dss_device *dst) |
|---|
| 4882 | +static void dsi_disconnect(struct omap_dss_device *src, |
|---|
| 4883 | + struct omap_dss_device *dst) |
|---|
| 4992 | 4884 | { |
|---|
| 4993 | | - struct dsi_data *dsi = to_dsi_data(dssdev); |
|---|
| 4994 | | - |
|---|
| 4995 | | - WARN_ON(dst != dssdev->dst); |
|---|
| 4996 | | - |
|---|
| 4997 | | - if (dst != dssdev->dst) |
|---|
| 4998 | | - return; |
|---|
| 4999 | | - |
|---|
| 5000 | | - omapdss_output_unset_device(dssdev); |
|---|
| 5001 | | - |
|---|
| 5002 | | - dss_mgr_disconnect(&dsi->output, dssdev); |
|---|
| 4885 | + omapdss_device_disconnect(dst, dst->next); |
|---|
| 5003 | 4886 | } |
|---|
| 5004 | 4887 | |
|---|
| 5005 | | -static const struct omapdss_dsi_ops dsi_ops = { |
|---|
| 4888 | +static const struct omap_dss_device_ops dsi_ops = { |
|---|
| 5006 | 4889 | .connect = dsi_connect, |
|---|
| 5007 | 4890 | .disconnect = dsi_disconnect, |
|---|
| 5008 | | - |
|---|
| 5009 | | - .bus_lock = dsi_bus_lock, |
|---|
| 5010 | | - .bus_unlock = dsi_bus_unlock, |
|---|
| 5011 | | - |
|---|
| 5012 | 4891 | .enable = dsi_display_enable, |
|---|
| 5013 | | - .disable = dsi_display_disable, |
|---|
| 5014 | 4892 | |
|---|
| 5015 | | - .enable_hs = dsi_vc_enable_hs, |
|---|
| 4893 | + .dsi = { |
|---|
| 4894 | + .bus_lock = dsi_bus_lock, |
|---|
| 4895 | + .bus_unlock = dsi_bus_unlock, |
|---|
| 5016 | 4896 | |
|---|
| 5017 | | - .configure_pins = dsi_configure_pins, |
|---|
| 5018 | | - .set_config = dsi_set_config, |
|---|
| 4897 | + .disable = dsi_display_disable, |
|---|
| 5019 | 4898 | |
|---|
| 5020 | | - .enable_video_output = dsi_enable_video_output, |
|---|
| 5021 | | - .disable_video_output = dsi_disable_video_output, |
|---|
| 4899 | + .enable_hs = dsi_vc_enable_hs, |
|---|
| 5022 | 4900 | |
|---|
| 5023 | | - .update = dsi_update, |
|---|
| 4901 | + .configure_pins = dsi_configure_pins, |
|---|
| 4902 | + .set_config = dsi_set_config, |
|---|
| 5024 | 4903 | |
|---|
| 5025 | | - .enable_te = dsi_enable_te, |
|---|
| 4904 | + .enable_video_output = dsi_enable_video_output, |
|---|
| 4905 | + .disable_video_output = dsi_disable_video_output, |
|---|
| 5026 | 4906 | |
|---|
| 5027 | | - .request_vc = dsi_request_vc, |
|---|
| 5028 | | - .set_vc_id = dsi_set_vc_id, |
|---|
| 5029 | | - .release_vc = dsi_release_vc, |
|---|
| 4907 | + .update = dsi_update, |
|---|
| 5030 | 4908 | |
|---|
| 5031 | | - .dcs_write = dsi_vc_dcs_write, |
|---|
| 5032 | | - .dcs_write_nosync = dsi_vc_dcs_write_nosync, |
|---|
| 5033 | | - .dcs_read = dsi_vc_dcs_read, |
|---|
| 4909 | + .enable_te = dsi_enable_te, |
|---|
| 5034 | 4910 | |
|---|
| 5035 | | - .gen_write = dsi_vc_generic_write, |
|---|
| 5036 | | - .gen_write_nosync = dsi_vc_generic_write_nosync, |
|---|
| 5037 | | - .gen_read = dsi_vc_generic_read, |
|---|
| 4911 | + .request_vc = dsi_request_vc, |
|---|
| 4912 | + .set_vc_id = dsi_set_vc_id, |
|---|
| 4913 | + .release_vc = dsi_release_vc, |
|---|
| 5038 | 4914 | |
|---|
| 5039 | | - .bta_sync = dsi_vc_send_bta_sync, |
|---|
| 4915 | + .dcs_write = dsi_vc_dcs_write, |
|---|
| 4916 | + .dcs_write_nosync = dsi_vc_dcs_write_nosync, |
|---|
| 4917 | + .dcs_read = dsi_vc_dcs_read, |
|---|
| 5040 | 4918 | |
|---|
| 5041 | | - .set_max_rx_packet_size = dsi_vc_set_max_rx_packet_size, |
|---|
| 4919 | + .gen_write = dsi_vc_generic_write, |
|---|
| 4920 | + .gen_write_nosync = dsi_vc_generic_write_nosync, |
|---|
| 4921 | + .gen_read = dsi_vc_generic_read, |
|---|
| 4922 | + |
|---|
| 4923 | + .bta_sync = dsi_vc_send_bta_sync, |
|---|
| 4924 | + |
|---|
| 4925 | + .set_max_rx_packet_size = dsi_vc_set_max_rx_packet_size, |
|---|
| 4926 | + }, |
|---|
| 5042 | 4927 | }; |
|---|
| 5043 | 4928 | |
|---|
| 5044 | | -static void dsi_init_output(struct dsi_data *dsi) |
|---|
| 5045 | | -{ |
|---|
| 5046 | | - struct omap_dss_device *out = &dsi->output; |
|---|
| 5047 | | - |
|---|
| 5048 | | - out->dev = dsi->dev; |
|---|
| 5049 | | - out->id = dsi->module_id == 0 ? |
|---|
| 5050 | | - OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2; |
|---|
| 5051 | | - |
|---|
| 5052 | | - out->output_type = OMAP_DISPLAY_TYPE_DSI; |
|---|
| 5053 | | - out->name = dsi->module_id == 0 ? "dsi.0" : "dsi.1"; |
|---|
| 5054 | | - out->dispc_channel = dsi_get_channel(dsi); |
|---|
| 5055 | | - out->ops.dsi = &dsi_ops; |
|---|
| 5056 | | - out->owner = THIS_MODULE; |
|---|
| 5057 | | - |
|---|
| 5058 | | - omapdss_register_output(out); |
|---|
| 5059 | | -} |
|---|
| 5060 | | - |
|---|
| 5061 | | -static void dsi_uninit_output(struct dsi_data *dsi) |
|---|
| 5062 | | -{ |
|---|
| 5063 | | - struct omap_dss_device *out = &dsi->output; |
|---|
| 5064 | | - |
|---|
| 5065 | | - omapdss_unregister_output(out); |
|---|
| 5066 | | -} |
|---|
| 5067 | | - |
|---|
| 5068 | | -static int dsi_probe_of(struct dsi_data *dsi) |
|---|
| 5069 | | -{ |
|---|
| 5070 | | - struct device_node *node = dsi->dev->of_node; |
|---|
| 5071 | | - struct property *prop; |
|---|
| 5072 | | - u32 lane_arr[10]; |
|---|
| 5073 | | - int len, num_pins; |
|---|
| 5074 | | - int r, i; |
|---|
| 5075 | | - struct device_node *ep; |
|---|
| 5076 | | - struct omap_dsi_pin_config pin_cfg; |
|---|
| 5077 | | - |
|---|
| 5078 | | - ep = of_graph_get_endpoint_by_regs(node, 0, 0); |
|---|
| 5079 | | - if (!ep) |
|---|
| 5080 | | - return 0; |
|---|
| 5081 | | - |
|---|
| 5082 | | - prop = of_find_property(ep, "lanes", &len); |
|---|
| 5083 | | - if (prop == NULL) { |
|---|
| 5084 | | - dev_err(dsi->dev, "failed to find lane data\n"); |
|---|
| 5085 | | - r = -EINVAL; |
|---|
| 5086 | | - goto err; |
|---|
| 5087 | | - } |
|---|
| 5088 | | - |
|---|
| 5089 | | - num_pins = len / sizeof(u32); |
|---|
| 5090 | | - |
|---|
| 5091 | | - if (num_pins < 4 || num_pins % 2 != 0 || |
|---|
| 5092 | | - num_pins > dsi->num_lanes_supported * 2) { |
|---|
| 5093 | | - dev_err(dsi->dev, "bad number of lanes\n"); |
|---|
| 5094 | | - r = -EINVAL; |
|---|
| 5095 | | - goto err; |
|---|
| 5096 | | - } |
|---|
| 5097 | | - |
|---|
| 5098 | | - r = of_property_read_u32_array(ep, "lanes", lane_arr, num_pins); |
|---|
| 5099 | | - if (r) { |
|---|
| 5100 | | - dev_err(dsi->dev, "failed to read lane data\n"); |
|---|
| 5101 | | - goto err; |
|---|
| 5102 | | - } |
|---|
| 5103 | | - |
|---|
| 5104 | | - pin_cfg.num_pins = num_pins; |
|---|
| 5105 | | - for (i = 0; i < num_pins; ++i) |
|---|
| 5106 | | - pin_cfg.pins[i] = (int)lane_arr[i]; |
|---|
| 5107 | | - |
|---|
| 5108 | | - r = dsi_configure_pins(&dsi->output, &pin_cfg); |
|---|
| 5109 | | - if (r) { |
|---|
| 5110 | | - dev_err(dsi->dev, "failed to configure pins"); |
|---|
| 5111 | | - goto err; |
|---|
| 5112 | | - } |
|---|
| 5113 | | - |
|---|
| 5114 | | - of_node_put(ep); |
|---|
| 5115 | | - |
|---|
| 5116 | | - return 0; |
|---|
| 5117 | | - |
|---|
| 5118 | | -err: |
|---|
| 5119 | | - of_node_put(ep); |
|---|
| 5120 | | - return r; |
|---|
| 5121 | | -} |
|---|
| 4929 | +/* ----------------------------------------------------------------------------- |
|---|
| 4930 | + * PLL |
|---|
| 4931 | + */ |
|---|
| 5122 | 4932 | |
|---|
| 5123 | 4933 | static const struct dss_pll_ops dsi_pll_ops = { |
|---|
| 5124 | 4934 | .enable = dsi_pll_enable, |
|---|
| .. | .. |
|---|
| 5233 | 5043 | return 0; |
|---|
| 5234 | 5044 | } |
|---|
| 5235 | 5045 | |
|---|
| 5236 | | -/* DSI1 HW IP initialisation */ |
|---|
| 5046 | +/* ----------------------------------------------------------------------------- |
|---|
| 5047 | + * Component Bind & Unbind |
|---|
| 5048 | + */ |
|---|
| 5049 | + |
|---|
| 5050 | +static int dsi_bind(struct device *dev, struct device *master, void *data) |
|---|
| 5051 | +{ |
|---|
| 5052 | + struct dss_device *dss = dss_get_device(master); |
|---|
| 5053 | + struct dsi_data *dsi = dev_get_drvdata(dev); |
|---|
| 5054 | + char name[10]; |
|---|
| 5055 | + u32 rev; |
|---|
| 5056 | + int r; |
|---|
| 5057 | + |
|---|
| 5058 | + dsi->dss = dss; |
|---|
| 5059 | + |
|---|
| 5060 | + dsi_init_pll_data(dss, dsi); |
|---|
| 5061 | + |
|---|
| 5062 | + r = dsi_runtime_get(dsi); |
|---|
| 5063 | + if (r) |
|---|
| 5064 | + return r; |
|---|
| 5065 | + |
|---|
| 5066 | + rev = dsi_read_reg(dsi, DSI_REVISION); |
|---|
| 5067 | + dev_dbg(dev, "OMAP DSI rev %d.%d\n", |
|---|
| 5068 | + FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); |
|---|
| 5069 | + |
|---|
| 5070 | + dsi->line_buffer_size = dsi_get_line_buf_size(dsi); |
|---|
| 5071 | + |
|---|
| 5072 | + dsi_runtime_put(dsi); |
|---|
| 5073 | + |
|---|
| 5074 | + snprintf(name, sizeof(name), "dsi%u_regs", dsi->module_id + 1); |
|---|
| 5075 | + dsi->debugfs.regs = dss_debugfs_create_file(dss, name, |
|---|
| 5076 | + dsi_dump_dsi_regs, dsi); |
|---|
| 5077 | +#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS |
|---|
| 5078 | + snprintf(name, sizeof(name), "dsi%u_irqs", dsi->module_id + 1); |
|---|
| 5079 | + dsi->debugfs.irqs = dss_debugfs_create_file(dss, name, |
|---|
| 5080 | + dsi_dump_dsi_irqs, dsi); |
|---|
| 5081 | +#endif |
|---|
| 5082 | + snprintf(name, sizeof(name), "dsi%u_clks", dsi->module_id + 1); |
|---|
| 5083 | + dsi->debugfs.clks = dss_debugfs_create_file(dss, name, |
|---|
| 5084 | + dsi_dump_dsi_clocks, dsi); |
|---|
| 5085 | + |
|---|
| 5086 | + return 0; |
|---|
| 5087 | +} |
|---|
| 5088 | + |
|---|
| 5089 | +static void dsi_unbind(struct device *dev, struct device *master, void *data) |
|---|
| 5090 | +{ |
|---|
| 5091 | + struct dsi_data *dsi = dev_get_drvdata(dev); |
|---|
| 5092 | + |
|---|
| 5093 | + dss_debugfs_remove_file(dsi->debugfs.clks); |
|---|
| 5094 | + dss_debugfs_remove_file(dsi->debugfs.irqs); |
|---|
| 5095 | + dss_debugfs_remove_file(dsi->debugfs.regs); |
|---|
| 5096 | + |
|---|
| 5097 | + WARN_ON(dsi->scp_clk_refcount > 0); |
|---|
| 5098 | + |
|---|
| 5099 | + dss_pll_unregister(&dsi->pll); |
|---|
| 5100 | +} |
|---|
| 5101 | + |
|---|
| 5102 | +static const struct component_ops dsi_component_ops = { |
|---|
| 5103 | + .bind = dsi_bind, |
|---|
| 5104 | + .unbind = dsi_unbind, |
|---|
| 5105 | +}; |
|---|
| 5106 | + |
|---|
| 5107 | +/* ----------------------------------------------------------------------------- |
|---|
| 5108 | + * Probe & Remove, Suspend & Resume |
|---|
| 5109 | + */ |
|---|
| 5110 | + |
|---|
| 5111 | +static int dsi_init_output(struct dsi_data *dsi) |
|---|
| 5112 | +{ |
|---|
| 5113 | + struct omap_dss_device *out = &dsi->output; |
|---|
| 5114 | + int r; |
|---|
| 5115 | + |
|---|
| 5116 | + out->dev = dsi->dev; |
|---|
| 5117 | + out->id = dsi->module_id == 0 ? |
|---|
| 5118 | + OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2; |
|---|
| 5119 | + |
|---|
| 5120 | + out->type = OMAP_DISPLAY_TYPE_DSI; |
|---|
| 5121 | + out->name = dsi->module_id == 0 ? "dsi.0" : "dsi.1"; |
|---|
| 5122 | + out->dispc_channel = dsi_get_channel(dsi); |
|---|
| 5123 | + out->ops = &dsi_ops; |
|---|
| 5124 | + out->owner = THIS_MODULE; |
|---|
| 5125 | + out->of_port = 0; |
|---|
| 5126 | + out->bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE |
|---|
| 5127 | + | DRM_BUS_FLAG_DE_HIGH |
|---|
| 5128 | + | DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE; |
|---|
| 5129 | + |
|---|
| 5130 | + r = omapdss_device_init_output(out, NULL); |
|---|
| 5131 | + if (r < 0) |
|---|
| 5132 | + return r; |
|---|
| 5133 | + |
|---|
| 5134 | + omapdss_device_register(out); |
|---|
| 5135 | + |
|---|
| 5136 | + return 0; |
|---|
| 5137 | +} |
|---|
| 5138 | + |
|---|
| 5139 | +static void dsi_uninit_output(struct dsi_data *dsi) |
|---|
| 5140 | +{ |
|---|
| 5141 | + struct omap_dss_device *out = &dsi->output; |
|---|
| 5142 | + |
|---|
| 5143 | + omapdss_device_unregister(out); |
|---|
| 5144 | + omapdss_device_cleanup_output(out); |
|---|
| 5145 | +} |
|---|
| 5146 | + |
|---|
| 5147 | +static int dsi_probe_of(struct dsi_data *dsi) |
|---|
| 5148 | +{ |
|---|
| 5149 | + struct device_node *node = dsi->dev->of_node; |
|---|
| 5150 | + struct property *prop; |
|---|
| 5151 | + u32 lane_arr[10]; |
|---|
| 5152 | + int len, num_pins; |
|---|
| 5153 | + int r, i; |
|---|
| 5154 | + struct device_node *ep; |
|---|
| 5155 | + struct omap_dsi_pin_config pin_cfg; |
|---|
| 5156 | + |
|---|
| 5157 | + ep = of_graph_get_endpoint_by_regs(node, 0, 0); |
|---|
| 5158 | + if (!ep) |
|---|
| 5159 | + return 0; |
|---|
| 5160 | + |
|---|
| 5161 | + prop = of_find_property(ep, "lanes", &len); |
|---|
| 5162 | + if (prop == NULL) { |
|---|
| 5163 | + dev_err(dsi->dev, "failed to find lane data\n"); |
|---|
| 5164 | + r = -EINVAL; |
|---|
| 5165 | + goto err; |
|---|
| 5166 | + } |
|---|
| 5167 | + |
|---|
| 5168 | + num_pins = len / sizeof(u32); |
|---|
| 5169 | + |
|---|
| 5170 | + if (num_pins < 4 || num_pins % 2 != 0 || |
|---|
| 5171 | + num_pins > dsi->num_lanes_supported * 2) { |
|---|
| 5172 | + dev_err(dsi->dev, "bad number of lanes\n"); |
|---|
| 5173 | + r = -EINVAL; |
|---|
| 5174 | + goto err; |
|---|
| 5175 | + } |
|---|
| 5176 | + |
|---|
| 5177 | + r = of_property_read_u32_array(ep, "lanes", lane_arr, num_pins); |
|---|
| 5178 | + if (r) { |
|---|
| 5179 | + dev_err(dsi->dev, "failed to read lane data\n"); |
|---|
| 5180 | + goto err; |
|---|
| 5181 | + } |
|---|
| 5182 | + |
|---|
| 5183 | + pin_cfg.num_pins = num_pins; |
|---|
| 5184 | + for (i = 0; i < num_pins; ++i) |
|---|
| 5185 | + pin_cfg.pins[i] = (int)lane_arr[i]; |
|---|
| 5186 | + |
|---|
| 5187 | + r = dsi_configure_pins(&dsi->output, &pin_cfg); |
|---|
| 5188 | + if (r) { |
|---|
| 5189 | + dev_err(dsi->dev, "failed to configure pins"); |
|---|
| 5190 | + goto err; |
|---|
| 5191 | + } |
|---|
| 5192 | + |
|---|
| 5193 | + of_node_put(ep); |
|---|
| 5194 | + |
|---|
| 5195 | + return 0; |
|---|
| 5196 | + |
|---|
| 5197 | +err: |
|---|
| 5198 | + of_node_put(ep); |
|---|
| 5199 | + return r; |
|---|
| 5200 | +} |
|---|
| 5201 | + |
|---|
| 5237 | 5202 | static const struct dsi_of_data dsi_of_data_omap34xx = { |
|---|
| 5238 | 5203 | .model = DSI_MODEL_OMAP3, |
|---|
| 5239 | 5204 | .pll_hw = &dss_omap3_dsi_pll_hw, |
|---|
| .. | .. |
|---|
| 5299 | 5264 | { /* sentinel */ } |
|---|
| 5300 | 5265 | }; |
|---|
| 5301 | 5266 | |
|---|
| 5302 | | -static int dsi_bind(struct device *dev, struct device *master, void *data) |
|---|
| 5267 | +static int dsi_probe(struct platform_device *pdev) |
|---|
| 5303 | 5268 | { |
|---|
| 5304 | | - struct platform_device *pdev = to_platform_device(dev); |
|---|
| 5305 | | - struct dss_device *dss = dss_get_device(master); |
|---|
| 5306 | 5269 | const struct soc_device_attribute *soc; |
|---|
| 5307 | 5270 | const struct dsi_module_id_data *d; |
|---|
| 5308 | | - u32 rev; |
|---|
| 5309 | | - int r, i; |
|---|
| 5271 | + struct device *dev = &pdev->dev; |
|---|
| 5310 | 5272 | struct dsi_data *dsi; |
|---|
| 5311 | 5273 | struct resource *dsi_mem; |
|---|
| 5312 | 5274 | struct resource *res; |
|---|
| 5275 | + unsigned int i; |
|---|
| 5276 | + int r; |
|---|
| 5313 | 5277 | |
|---|
| 5314 | 5278 | dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL); |
|---|
| 5315 | 5279 | if (!dsi) |
|---|
| 5316 | 5280 | return -ENOMEM; |
|---|
| 5317 | 5281 | |
|---|
| 5318 | | - dsi->dss = dss; |
|---|
| 5319 | 5282 | dsi->dev = dev; |
|---|
| 5320 | 5283 | dev_set_drvdata(dev, dsi); |
|---|
| 5321 | 5284 | |
|---|
| .. | .. |
|---|
| 5366 | 5329 | return r; |
|---|
| 5367 | 5330 | } |
|---|
| 5368 | 5331 | |
|---|
| 5332 | + dsi->vdds_dsi_reg = devm_regulator_get(dev, "vdd"); |
|---|
| 5333 | + if (IS_ERR(dsi->vdds_dsi_reg)) { |
|---|
| 5334 | + if (PTR_ERR(dsi->vdds_dsi_reg) != -EPROBE_DEFER) |
|---|
| 5335 | + DSSERR("can't get DSI VDD regulator\n"); |
|---|
| 5336 | + return PTR_ERR(dsi->vdds_dsi_reg); |
|---|
| 5337 | + } |
|---|
| 5338 | + |
|---|
| 5369 | 5339 | soc = soc_device_match(dsi_soc_devices); |
|---|
| 5370 | 5340 | if (soc) |
|---|
| 5371 | 5341 | dsi->data = soc->data; |
|---|
| .. | .. |
|---|
| 5412 | 5382 | if (r) |
|---|
| 5413 | 5383 | return r; |
|---|
| 5414 | 5384 | |
|---|
| 5415 | | - dsi_init_pll_data(dss, dsi); |
|---|
| 5416 | | - |
|---|
| 5417 | 5385 | pm_runtime_enable(dev); |
|---|
| 5418 | | - |
|---|
| 5419 | | - r = dsi_runtime_get(dsi); |
|---|
| 5420 | | - if (r) |
|---|
| 5421 | | - goto err_runtime_get; |
|---|
| 5422 | | - |
|---|
| 5423 | | - rev = dsi_read_reg(dsi, DSI_REVISION); |
|---|
| 5424 | | - dev_dbg(dev, "OMAP DSI rev %d.%d\n", |
|---|
| 5425 | | - FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); |
|---|
| 5426 | 5386 | |
|---|
| 5427 | 5387 | /* DSI on OMAP3 doesn't have register DSI_GNQ, set number |
|---|
| 5428 | 5388 | * of data to 3 by default */ |
|---|
| 5429 | | - if (dsi->data->quirks & DSI_QUIRK_GNQ) |
|---|
| 5389 | + if (dsi->data->quirks & DSI_QUIRK_GNQ) { |
|---|
| 5390 | + dsi_runtime_get(dsi); |
|---|
| 5430 | 5391 | /* NB_DATA_LANES */ |
|---|
| 5431 | 5392 | dsi->num_lanes_supported = 1 + REG_GET(dsi, DSI_GNQ, 11, 9); |
|---|
| 5432 | | - else |
|---|
| 5393 | + dsi_runtime_put(dsi); |
|---|
| 5394 | + } else { |
|---|
| 5433 | 5395 | dsi->num_lanes_supported = 3; |
|---|
| 5396 | + } |
|---|
| 5434 | 5397 | |
|---|
| 5435 | | - dsi->line_buffer_size = dsi_get_line_buf_size(dsi); |
|---|
| 5398 | + r = of_platform_populate(dev->of_node, NULL, NULL, dev); |
|---|
| 5399 | + if (r) { |
|---|
| 5400 | + DSSERR("Failed to populate DSI child devices: %d\n", r); |
|---|
| 5401 | + goto err_pm_disable; |
|---|
| 5402 | + } |
|---|
| 5436 | 5403 | |
|---|
| 5437 | | - dsi_init_output(dsi); |
|---|
| 5404 | + r = dsi_init_output(dsi); |
|---|
| 5405 | + if (r) |
|---|
| 5406 | + goto err_of_depopulate; |
|---|
| 5438 | 5407 | |
|---|
| 5439 | 5408 | r = dsi_probe_of(dsi); |
|---|
| 5440 | 5409 | if (r) { |
|---|
| 5441 | 5410 | DSSERR("Invalid DSI DT data\n"); |
|---|
| 5442 | | - goto err_probe_of; |
|---|
| 5411 | + goto err_uninit_output; |
|---|
| 5443 | 5412 | } |
|---|
| 5444 | 5413 | |
|---|
| 5445 | | - r = of_platform_populate(dev->of_node, NULL, NULL, dev); |
|---|
| 5414 | + r = component_add(&pdev->dev, &dsi_component_ops); |
|---|
| 5446 | 5415 | if (r) |
|---|
| 5447 | | - DSSERR("Failed to populate DSI child devices: %d\n", r); |
|---|
| 5448 | | - |
|---|
| 5449 | | - dsi_runtime_put(dsi); |
|---|
| 5450 | | - |
|---|
| 5451 | | - if (dsi->module_id == 0) |
|---|
| 5452 | | - dsi->debugfs.regs = dss_debugfs_create_file(dss, "dsi1_regs", |
|---|
| 5453 | | - dsi1_dump_regs, |
|---|
| 5454 | | - &dsi); |
|---|
| 5455 | | - else |
|---|
| 5456 | | - dsi->debugfs.regs = dss_debugfs_create_file(dss, "dsi2_regs", |
|---|
| 5457 | | - dsi2_dump_regs, |
|---|
| 5458 | | - &dsi); |
|---|
| 5459 | | -#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS |
|---|
| 5460 | | - if (dsi->module_id == 0) |
|---|
| 5461 | | - dsi->debugfs.irqs = dss_debugfs_create_file(dss, "dsi1_irqs", |
|---|
| 5462 | | - dsi1_dump_irqs, |
|---|
| 5463 | | - &dsi); |
|---|
| 5464 | | - else |
|---|
| 5465 | | - dsi->debugfs.irqs = dss_debugfs_create_file(dss, "dsi2_irqs", |
|---|
| 5466 | | - dsi2_dump_irqs, |
|---|
| 5467 | | - &dsi); |
|---|
| 5468 | | -#endif |
|---|
| 5416 | + goto err_uninit_output; |
|---|
| 5469 | 5417 | |
|---|
| 5470 | 5418 | return 0; |
|---|
| 5471 | 5419 | |
|---|
| 5472 | | -err_probe_of: |
|---|
| 5420 | +err_uninit_output: |
|---|
| 5473 | 5421 | dsi_uninit_output(dsi); |
|---|
| 5474 | | - dsi_runtime_put(dsi); |
|---|
| 5475 | | - |
|---|
| 5476 | | -err_runtime_get: |
|---|
| 5422 | +err_of_depopulate: |
|---|
| 5423 | + of_platform_depopulate(dev); |
|---|
| 5424 | +err_pm_disable: |
|---|
| 5477 | 5425 | pm_runtime_disable(dev); |
|---|
| 5478 | 5426 | return r; |
|---|
| 5479 | 5427 | } |
|---|
| 5480 | 5428 | |
|---|
| 5481 | | -static void dsi_unbind(struct device *dev, struct device *master, void *data) |
|---|
| 5429 | +static int dsi_remove(struct platform_device *pdev) |
|---|
| 5482 | 5430 | { |
|---|
| 5483 | | - struct dsi_data *dsi = dev_get_drvdata(dev); |
|---|
| 5431 | + struct dsi_data *dsi = platform_get_drvdata(pdev); |
|---|
| 5484 | 5432 | |
|---|
| 5485 | | - dss_debugfs_remove_file(dsi->debugfs.irqs); |
|---|
| 5486 | | - dss_debugfs_remove_file(dsi->debugfs.regs); |
|---|
| 5487 | | - |
|---|
| 5488 | | - of_platform_depopulate(dev); |
|---|
| 5489 | | - |
|---|
| 5490 | | - WARN_ON(dsi->scp_clk_refcount > 0); |
|---|
| 5491 | | - |
|---|
| 5492 | | - dss_pll_unregister(&dsi->pll); |
|---|
| 5433 | + component_del(&pdev->dev, &dsi_component_ops); |
|---|
| 5493 | 5434 | |
|---|
| 5494 | 5435 | dsi_uninit_output(dsi); |
|---|
| 5495 | 5436 | |
|---|
| 5496 | | - pm_runtime_disable(dev); |
|---|
| 5437 | + of_platform_depopulate(&pdev->dev); |
|---|
| 5438 | + |
|---|
| 5439 | + pm_runtime_disable(&pdev->dev); |
|---|
| 5497 | 5440 | |
|---|
| 5498 | 5441 | if (dsi->vdds_dsi_reg != NULL && dsi->vdds_dsi_enabled) { |
|---|
| 5499 | 5442 | regulator_disable(dsi->vdds_dsi_reg); |
|---|
| 5500 | 5443 | dsi->vdds_dsi_enabled = false; |
|---|
| 5501 | 5444 | } |
|---|
| 5502 | | -} |
|---|
| 5503 | 5445 | |
|---|
| 5504 | | -static const struct component_ops dsi_component_ops = { |
|---|
| 5505 | | - .bind = dsi_bind, |
|---|
| 5506 | | - .unbind = dsi_unbind, |
|---|
| 5507 | | -}; |
|---|
| 5508 | | - |
|---|
| 5509 | | -static int dsi_probe(struct platform_device *pdev) |
|---|
| 5510 | | -{ |
|---|
| 5511 | | - return component_add(&pdev->dev, &dsi_component_ops); |
|---|
| 5512 | | -} |
|---|
| 5513 | | - |
|---|
| 5514 | | -static int dsi_remove(struct platform_device *pdev) |
|---|
| 5515 | | -{ |
|---|
| 5516 | | - component_del(&pdev->dev, &dsi_component_ops); |
|---|
| 5517 | 5446 | return 0; |
|---|
| 5518 | 5447 | } |
|---|
| 5519 | 5448 | |
|---|
| .. | .. |
|---|
| 5527 | 5456 | /* wait for current handler to finish before turning the DSI off */ |
|---|
| 5528 | 5457 | synchronize_irq(dsi->irq); |
|---|
| 5529 | 5458 | |
|---|
| 5530 | | - dispc_runtime_put(dsi->dss->dispc); |
|---|
| 5531 | | - |
|---|
| 5532 | 5459 | return 0; |
|---|
| 5533 | 5460 | } |
|---|
| 5534 | 5461 | |
|---|
| 5535 | 5462 | static int dsi_runtime_resume(struct device *dev) |
|---|
| 5536 | 5463 | { |
|---|
| 5537 | 5464 | struct dsi_data *dsi = dev_get_drvdata(dev); |
|---|
| 5538 | | - int r; |
|---|
| 5539 | | - |
|---|
| 5540 | | - r = dispc_runtime_get(dsi->dss->dispc); |
|---|
| 5541 | | - if (r) |
|---|
| 5542 | | - return r; |
|---|
| 5543 | 5465 | |
|---|
| 5544 | 5466 | dsi->is_enabled = true; |
|---|
| 5545 | 5467 | /* ensure the irq handler sees the is_enabled value */ |
|---|
| .. | .. |
|---|
| 5551 | 5473 | static const struct dev_pm_ops dsi_pm_ops = { |
|---|
| 5552 | 5474 | .runtime_suspend = dsi_runtime_suspend, |
|---|
| 5553 | 5475 | .runtime_resume = dsi_runtime_resume, |
|---|
| 5476 | + SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) |
|---|
| 5554 | 5477 | }; |
|---|
| 5555 | 5478 | |
|---|
| 5556 | 5479 | struct platform_driver omap_dsihw_driver = { |
|---|