| .. | .. |
|---|
| 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 | 1447 | struct dsi_irq_stats stats; |
|---|
| 1511 | 1448 | |
|---|
| .. | .. |
|---|
| 1589 | 1526 | PIS(ULPSACTIVENOT_ALL0); |
|---|
| 1590 | 1527 | PIS(ULPSACTIVENOT_ALL1); |
|---|
| 1591 | 1528 | #undef PIS |
|---|
| 1592 | | -} |
|---|
| 1593 | 1529 | |
|---|
| 1594 | | -static int dsi1_dump_irqs(struct seq_file *s, void *p) |
|---|
| 1595 | | -{ |
|---|
| 1596 | | - struct dsi_data *dsi = dsi_get_dsi_from_id(0); |
|---|
| 1597 | | - |
|---|
| 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 | 1530 | return 0; |
|---|
| 1608 | 1531 | } |
|---|
| 1609 | 1532 | #endif |
|---|
| 1610 | 1533 | |
|---|
| 1611 | | -static void dsi_dump_dsi_regs(struct dsi_data *dsi, struct seq_file *s) |
|---|
| 1534 | +static int dsi_dump_dsi_regs(struct seq_file *s, void *p) |
|---|
| 1612 | 1535 | { |
|---|
| 1613 | | -#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsi, r)) |
|---|
| 1536 | + struct dsi_data *dsi = s->private; |
|---|
| 1614 | 1537 | |
|---|
| 1615 | 1538 | if (dsi_runtime_get(dsi)) |
|---|
| 1616 | | - return; |
|---|
| 1539 | + return 0; |
|---|
| 1617 | 1540 | dsi_enable_scp_clk(dsi); |
|---|
| 1618 | 1541 | |
|---|
| 1542 | +#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsi, r)) |
|---|
| 1619 | 1543 | DUMPREG(DSI_REVISION); |
|---|
| 1620 | 1544 | DUMPREG(DSI_SYSCONFIG); |
|---|
| 1621 | 1545 | DUMPREG(DSI_SYSSTATUS); |
|---|
| .. | .. |
|---|
| 1685 | 1609 | DUMPREG(DSI_PLL_GO); |
|---|
| 1686 | 1610 | DUMPREG(DSI_PLL_CONFIGURATION1); |
|---|
| 1687 | 1611 | DUMPREG(DSI_PLL_CONFIGURATION2); |
|---|
| 1612 | +#undef DUMPREG |
|---|
| 1688 | 1613 | |
|---|
| 1689 | 1614 | dsi_disable_scp_clk(dsi); |
|---|
| 1690 | 1615 | dsi_runtime_put(dsi); |
|---|
| 1691 | | -#undef DUMPREG |
|---|
| 1692 | | -} |
|---|
| 1693 | 1616 | |
|---|
| 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 | 1617 | return 0; |
|---|
| 1708 | 1618 | } |
|---|
| 1709 | 1619 | |
|---|
| .. | .. |
|---|
| 3330 | 3240 | |
|---|
| 3331 | 3241 | if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { |
|---|
| 3332 | 3242 | int bpp = dsi_get_pixel_size(dsi->pix_fmt); |
|---|
| 3333 | | - struct videomode *vm = &dsi->vm; |
|---|
| 3243 | + const struct videomode *vm = &dsi->vm; |
|---|
| 3334 | 3244 | /* |
|---|
| 3335 | 3245 | * Don't use line buffers if width is greater than the video |
|---|
| 3336 | 3246 | * port's line buffer size |
|---|
| .. | .. |
|---|
| 3459 | 3369 | int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat; |
|---|
| 3460 | 3370 | int tclk_trail, ths_exit, exiths_clk; |
|---|
| 3461 | 3371 | bool ddr_alwon; |
|---|
| 3462 | | - struct videomode *vm = &dsi->vm; |
|---|
| 3372 | + const struct videomode *vm = &dsi->vm; |
|---|
| 3463 | 3373 | int bpp = dsi_get_pixel_size(dsi->pix_fmt); |
|---|
| 3464 | 3374 | int ndl = dsi->num_lanes_used - 1; |
|---|
| 3465 | 3375 | int dsi_fclk_hsdiv = dsi->user_dsi_cinfo.mX[HSDIV_DSI] + 1; |
|---|
| .. | .. |
|---|
| 3638 | 3548 | |
|---|
| 3639 | 3549 | static void dsi_proto_timings(struct dsi_data *dsi) |
|---|
| 3640 | 3550 | { |
|---|
| 3641 | | - unsigned int tlpx, tclk_zero, tclk_prepare, tclk_trail; |
|---|
| 3551 | + unsigned int tlpx, tclk_zero, tclk_prepare; |
|---|
| 3642 | 3552 | unsigned int tclk_pre, tclk_post; |
|---|
| 3643 | 3553 | unsigned int ths_prepare, ths_prepare_ths_zero, ths_zero; |
|---|
| 3644 | 3554 | unsigned int ths_trail, ths_exit; |
|---|
| .. | .. |
|---|
| 3657 | 3567 | |
|---|
| 3658 | 3568 | r = dsi_read_reg(dsi, DSI_DSIPHY_CFG1); |
|---|
| 3659 | 3569 | tlpx = FLD_GET(r, 20, 16) * 2; |
|---|
| 3660 | | - tclk_trail = FLD_GET(r, 15, 8); |
|---|
| 3661 | 3570 | tclk_zero = FLD_GET(r, 7, 0); |
|---|
| 3662 | 3571 | |
|---|
| 3663 | 3572 | r = dsi_read_reg(dsi, DSI_DSIPHY_CFG2); |
|---|
| .. | .. |
|---|
| 3709 | 3618 | int vbp = dsi->vm_timings.vbp; |
|---|
| 3710 | 3619 | int window_sync = dsi->vm_timings.window_sync; |
|---|
| 3711 | 3620 | bool hsync_end; |
|---|
| 3712 | | - struct videomode *vm = &dsi->vm; |
|---|
| 3621 | + const struct videomode *vm = &dsi->vm; |
|---|
| 3713 | 3622 | int bpp = dsi_get_pixel_size(dsi->pix_fmt); |
|---|
| 3714 | 3623 | int tl, t_he, width_bytes; |
|---|
| 3715 | 3624 | |
|---|
| .. | .. |
|---|
| 3818 | 3727 | { |
|---|
| 3819 | 3728 | struct dsi_data *dsi = to_dsi_data(dssdev); |
|---|
| 3820 | 3729 | int bpp = dsi_get_pixel_size(dsi->pix_fmt); |
|---|
| 3821 | | - struct omap_dss_device *out = &dsi->output; |
|---|
| 3822 | 3730 | u8 data_type; |
|---|
| 3823 | 3731 | u16 word_count; |
|---|
| 3824 | 3732 | int r; |
|---|
| 3825 | 3733 | |
|---|
| 3826 | | - if (!out->dispc_channel_connected) { |
|---|
| 3827 | | - DSSERR("failed to enable display: no output/manager\n"); |
|---|
| 3828 | | - return -ENODEV; |
|---|
| 3829 | | - } |
|---|
| 3830 | | - |
|---|
| 3831 | 3734 | r = dsi_display_init_dispc(dsi); |
|---|
| 3832 | 3735 | if (r) |
|---|
| 3833 | | - goto err_init_dispc; |
|---|
| 3736 | + return r; |
|---|
| 3834 | 3737 | |
|---|
| 3835 | 3738 | if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { |
|---|
| 3836 | 3739 | switch (dsi->pix_fmt) { |
|---|
| .. | .. |
|---|
| 3879 | 3782 | } |
|---|
| 3880 | 3783 | err_pix_fmt: |
|---|
| 3881 | 3784 | dsi_display_uninit_dispc(dsi); |
|---|
| 3882 | | -err_init_dispc: |
|---|
| 3883 | 3785 | return r; |
|---|
| 3884 | 3786 | } |
|---|
| 3885 | 3787 | |
|---|
| .. | .. |
|---|
| 3965 | 3867 | r = schedule_delayed_work(&dsi->framedone_timeout_work, |
|---|
| 3966 | 3868 | msecs_to_jiffies(250)); |
|---|
| 3967 | 3869 | BUG_ON(r == 0); |
|---|
| 3968 | | - |
|---|
| 3969 | | - dss_mgr_set_timings(&dsi->output, &dsi->vm); |
|---|
| 3970 | 3870 | |
|---|
| 3971 | 3871 | dss_mgr_start_update(&dsi->output); |
|---|
| 3972 | 3872 | |
|---|
| .. | .. |
|---|
| 4109 | 4009 | dsi->mgr_config.fifohandcheck = false; |
|---|
| 4110 | 4010 | } |
|---|
| 4111 | 4011 | |
|---|
| 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 | 4012 | r = dsi_configure_dispc_clocks(dsi); |
|---|
| 4131 | 4013 | if (r) |
|---|
| 4132 | 4014 | goto err1; |
|---|
| .. | .. |
|---|
| 4262 | 4144 | } |
|---|
| 4263 | 4145 | } |
|---|
| 4264 | 4146 | |
|---|
| 4265 | | -static int dsi_display_enable(struct omap_dss_device *dssdev) |
|---|
| 4147 | +static void dsi_display_enable(struct omap_dss_device *dssdev) |
|---|
| 4266 | 4148 | { |
|---|
| 4267 | 4149 | struct dsi_data *dsi = to_dsi_data(dssdev); |
|---|
| 4268 | | - int r = 0; |
|---|
| 4150 | + int r; |
|---|
| 4269 | 4151 | |
|---|
| 4270 | 4152 | DSSDBG("dsi_display_enable\n"); |
|---|
| 4271 | 4153 | |
|---|
| .. | .. |
|---|
| 4285 | 4167 | |
|---|
| 4286 | 4168 | mutex_unlock(&dsi->lock); |
|---|
| 4287 | 4169 | |
|---|
| 4288 | | - return 0; |
|---|
| 4170 | + return; |
|---|
| 4289 | 4171 | |
|---|
| 4290 | 4172 | err_init_dsi: |
|---|
| 4291 | 4173 | dsi_runtime_put(dsi); |
|---|
| 4292 | 4174 | err_get_dsi: |
|---|
| 4293 | 4175 | mutex_unlock(&dsi->lock); |
|---|
| 4294 | 4176 | DSSDBG("dsi_display_enable FAILED\n"); |
|---|
| 4295 | | - return r; |
|---|
| 4296 | 4177 | } |
|---|
| 4297 | 4178 | |
|---|
| 4298 | 4179 | static void dsi_display_disable(struct omap_dss_device *dssdev, |
|---|
| .. | .. |
|---|
| 4842 | 4723 | dsi->user_dispc_cinfo = ctx.dispc_cinfo; |
|---|
| 4843 | 4724 | |
|---|
| 4844 | 4725 | dsi->vm = ctx.vm; |
|---|
| 4726 | + |
|---|
| 4727 | + /* |
|---|
| 4728 | + * override interlace, logic level and edge related parameters in |
|---|
| 4729 | + * videomode with default values |
|---|
| 4730 | + */ |
|---|
| 4731 | + dsi->vm.flags &= ~DISPLAY_FLAGS_INTERLACED; |
|---|
| 4732 | + dsi->vm.flags &= ~DISPLAY_FLAGS_HSYNC_LOW; |
|---|
| 4733 | + dsi->vm.flags |= DISPLAY_FLAGS_HSYNC_HIGH; |
|---|
| 4734 | + dsi->vm.flags &= ~DISPLAY_FLAGS_VSYNC_LOW; |
|---|
| 4735 | + dsi->vm.flags |= DISPLAY_FLAGS_VSYNC_HIGH; |
|---|
| 4736 | + /* |
|---|
| 4737 | + * HACK: These flags should be handled through the omap_dss_device bus |
|---|
| 4738 | + * flags, but this will only be possible when the DSI encoder will be |
|---|
| 4739 | + * converted to the omapdrm-managed encoder model. |
|---|
| 4740 | + */ |
|---|
| 4741 | + dsi->vm.flags &= ~DISPLAY_FLAGS_PIXDATA_NEGEDGE; |
|---|
| 4742 | + dsi->vm.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE; |
|---|
| 4743 | + dsi->vm.flags &= ~DISPLAY_FLAGS_DE_LOW; |
|---|
| 4744 | + dsi->vm.flags |= DISPLAY_FLAGS_DE_HIGH; |
|---|
| 4745 | + dsi->vm.flags &= ~DISPLAY_FLAGS_SYNC_POSEDGE; |
|---|
| 4746 | + dsi->vm.flags |= DISPLAY_FLAGS_SYNC_NEGEDGE; |
|---|
| 4747 | + |
|---|
| 4748 | + dss_mgr_set_timings(&dsi->output, &dsi->vm); |
|---|
| 4749 | + |
|---|
| 4845 | 4750 | dsi->vm_timings = ctx.dsi_vm; |
|---|
| 4846 | 4751 | |
|---|
| 4847 | 4752 | mutex_unlock(&dsi->lock); |
|---|
| .. | .. |
|---|
| 4962 | 4867 | return 0; |
|---|
| 4963 | 4868 | } |
|---|
| 4964 | 4869 | |
|---|
| 4965 | | -static int dsi_connect(struct omap_dss_device *dssdev, |
|---|
| 4966 | | - struct omap_dss_device *dst) |
|---|
| 4870 | +static int dsi_connect(struct omap_dss_device *src, |
|---|
| 4871 | + struct omap_dss_device *dst) |
|---|
| 4967 | 4872 | { |
|---|
| 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; |
|---|
| 4873 | + return omapdss_device_connect(dst->dss, dst, dst->next); |
|---|
| 4988 | 4874 | } |
|---|
| 4989 | 4875 | |
|---|
| 4990 | | -static void dsi_disconnect(struct omap_dss_device *dssdev, |
|---|
| 4991 | | - struct omap_dss_device *dst) |
|---|
| 4876 | +static void dsi_disconnect(struct omap_dss_device *src, |
|---|
| 4877 | + struct omap_dss_device *dst) |
|---|
| 4992 | 4878 | { |
|---|
| 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); |
|---|
| 4879 | + omapdss_device_disconnect(dst, dst->next); |
|---|
| 5003 | 4880 | } |
|---|
| 5004 | 4881 | |
|---|
| 5005 | | -static const struct omapdss_dsi_ops dsi_ops = { |
|---|
| 4882 | +static const struct omap_dss_device_ops dsi_ops = { |
|---|
| 5006 | 4883 | .connect = dsi_connect, |
|---|
| 5007 | 4884 | .disconnect = dsi_disconnect, |
|---|
| 5008 | | - |
|---|
| 5009 | | - .bus_lock = dsi_bus_lock, |
|---|
| 5010 | | - .bus_unlock = dsi_bus_unlock, |
|---|
| 5011 | | - |
|---|
| 5012 | 4885 | .enable = dsi_display_enable, |
|---|
| 5013 | | - .disable = dsi_display_disable, |
|---|
| 5014 | 4886 | |
|---|
| 5015 | | - .enable_hs = dsi_vc_enable_hs, |
|---|
| 4887 | + .dsi = { |
|---|
| 4888 | + .bus_lock = dsi_bus_lock, |
|---|
| 4889 | + .bus_unlock = dsi_bus_unlock, |
|---|
| 5016 | 4890 | |
|---|
| 5017 | | - .configure_pins = dsi_configure_pins, |
|---|
| 5018 | | - .set_config = dsi_set_config, |
|---|
| 4891 | + .disable = dsi_display_disable, |
|---|
| 5019 | 4892 | |
|---|
| 5020 | | - .enable_video_output = dsi_enable_video_output, |
|---|
| 5021 | | - .disable_video_output = dsi_disable_video_output, |
|---|
| 4893 | + .enable_hs = dsi_vc_enable_hs, |
|---|
| 5022 | 4894 | |
|---|
| 5023 | | - .update = dsi_update, |
|---|
| 4895 | + .configure_pins = dsi_configure_pins, |
|---|
| 4896 | + .set_config = dsi_set_config, |
|---|
| 5024 | 4897 | |
|---|
| 5025 | | - .enable_te = dsi_enable_te, |
|---|
| 4898 | + .enable_video_output = dsi_enable_video_output, |
|---|
| 4899 | + .disable_video_output = dsi_disable_video_output, |
|---|
| 5026 | 4900 | |
|---|
| 5027 | | - .request_vc = dsi_request_vc, |
|---|
| 5028 | | - .set_vc_id = dsi_set_vc_id, |
|---|
| 5029 | | - .release_vc = dsi_release_vc, |
|---|
| 4901 | + .update = dsi_update, |
|---|
| 5030 | 4902 | |
|---|
| 5031 | | - .dcs_write = dsi_vc_dcs_write, |
|---|
| 5032 | | - .dcs_write_nosync = dsi_vc_dcs_write_nosync, |
|---|
| 5033 | | - .dcs_read = dsi_vc_dcs_read, |
|---|
| 4903 | + .enable_te = dsi_enable_te, |
|---|
| 5034 | 4904 | |
|---|
| 5035 | | - .gen_write = dsi_vc_generic_write, |
|---|
| 5036 | | - .gen_write_nosync = dsi_vc_generic_write_nosync, |
|---|
| 5037 | | - .gen_read = dsi_vc_generic_read, |
|---|
| 4905 | + .request_vc = dsi_request_vc, |
|---|
| 4906 | + .set_vc_id = dsi_set_vc_id, |
|---|
| 4907 | + .release_vc = dsi_release_vc, |
|---|
| 5038 | 4908 | |
|---|
| 5039 | | - .bta_sync = dsi_vc_send_bta_sync, |
|---|
| 4909 | + .dcs_write = dsi_vc_dcs_write, |
|---|
| 4910 | + .dcs_write_nosync = dsi_vc_dcs_write_nosync, |
|---|
| 4911 | + .dcs_read = dsi_vc_dcs_read, |
|---|
| 5040 | 4912 | |
|---|
| 5041 | | - .set_max_rx_packet_size = dsi_vc_set_max_rx_packet_size, |
|---|
| 4913 | + .gen_write = dsi_vc_generic_write, |
|---|
| 4914 | + .gen_write_nosync = dsi_vc_generic_write_nosync, |
|---|
| 4915 | + .gen_read = dsi_vc_generic_read, |
|---|
| 4916 | + |
|---|
| 4917 | + .bta_sync = dsi_vc_send_bta_sync, |
|---|
| 4918 | + |
|---|
| 4919 | + .set_max_rx_packet_size = dsi_vc_set_max_rx_packet_size, |
|---|
| 4920 | + }, |
|---|
| 5042 | 4921 | }; |
|---|
| 5043 | 4922 | |
|---|
| 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 | | -} |
|---|
| 4923 | +/* ----------------------------------------------------------------------------- |
|---|
| 4924 | + * PLL |
|---|
| 4925 | + */ |
|---|
| 5122 | 4926 | |
|---|
| 5123 | 4927 | static const struct dss_pll_ops dsi_pll_ops = { |
|---|
| 5124 | 4928 | .enable = dsi_pll_enable, |
|---|
| .. | .. |
|---|
| 5233 | 5037 | return 0; |
|---|
| 5234 | 5038 | } |
|---|
| 5235 | 5039 | |
|---|
| 5236 | | -/* DSI1 HW IP initialisation */ |
|---|
| 5040 | +/* ----------------------------------------------------------------------------- |
|---|
| 5041 | + * Component Bind & Unbind |
|---|
| 5042 | + */ |
|---|
| 5043 | + |
|---|
| 5044 | +static int dsi_bind(struct device *dev, struct device *master, void *data) |
|---|
| 5045 | +{ |
|---|
| 5046 | + struct dss_device *dss = dss_get_device(master); |
|---|
| 5047 | + struct dsi_data *dsi = dev_get_drvdata(dev); |
|---|
| 5048 | + char name[10]; |
|---|
| 5049 | + u32 rev; |
|---|
| 5050 | + int r; |
|---|
| 5051 | + |
|---|
| 5052 | + dsi->dss = dss; |
|---|
| 5053 | + |
|---|
| 5054 | + dsi_init_pll_data(dss, dsi); |
|---|
| 5055 | + |
|---|
| 5056 | + r = dsi_runtime_get(dsi); |
|---|
| 5057 | + if (r) |
|---|
| 5058 | + return r; |
|---|
| 5059 | + |
|---|
| 5060 | + rev = dsi_read_reg(dsi, DSI_REVISION); |
|---|
| 5061 | + dev_dbg(dev, "OMAP DSI rev %d.%d\n", |
|---|
| 5062 | + FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); |
|---|
| 5063 | + |
|---|
| 5064 | + dsi->line_buffer_size = dsi_get_line_buf_size(dsi); |
|---|
| 5065 | + |
|---|
| 5066 | + dsi_runtime_put(dsi); |
|---|
| 5067 | + |
|---|
| 5068 | + snprintf(name, sizeof(name), "dsi%u_regs", dsi->module_id + 1); |
|---|
| 5069 | + dsi->debugfs.regs = dss_debugfs_create_file(dss, name, |
|---|
| 5070 | + dsi_dump_dsi_regs, dsi); |
|---|
| 5071 | +#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS |
|---|
| 5072 | + snprintf(name, sizeof(name), "dsi%u_irqs", dsi->module_id + 1); |
|---|
| 5073 | + dsi->debugfs.irqs = dss_debugfs_create_file(dss, name, |
|---|
| 5074 | + dsi_dump_dsi_irqs, dsi); |
|---|
| 5075 | +#endif |
|---|
| 5076 | + snprintf(name, sizeof(name), "dsi%u_clks", dsi->module_id + 1); |
|---|
| 5077 | + dsi->debugfs.clks = dss_debugfs_create_file(dss, name, |
|---|
| 5078 | + dsi_dump_dsi_clocks, dsi); |
|---|
| 5079 | + |
|---|
| 5080 | + return 0; |
|---|
| 5081 | +} |
|---|
| 5082 | + |
|---|
| 5083 | +static void dsi_unbind(struct device *dev, struct device *master, void *data) |
|---|
| 5084 | +{ |
|---|
| 5085 | + struct dsi_data *dsi = dev_get_drvdata(dev); |
|---|
| 5086 | + |
|---|
| 5087 | + dss_debugfs_remove_file(dsi->debugfs.clks); |
|---|
| 5088 | + dss_debugfs_remove_file(dsi->debugfs.irqs); |
|---|
| 5089 | + dss_debugfs_remove_file(dsi->debugfs.regs); |
|---|
| 5090 | + |
|---|
| 5091 | + WARN_ON(dsi->scp_clk_refcount > 0); |
|---|
| 5092 | + |
|---|
| 5093 | + dss_pll_unregister(&dsi->pll); |
|---|
| 5094 | +} |
|---|
| 5095 | + |
|---|
| 5096 | +static const struct component_ops dsi_component_ops = { |
|---|
| 5097 | + .bind = dsi_bind, |
|---|
| 5098 | + .unbind = dsi_unbind, |
|---|
| 5099 | +}; |
|---|
| 5100 | + |
|---|
| 5101 | +/* ----------------------------------------------------------------------------- |
|---|
| 5102 | + * Probe & Remove, Suspend & Resume |
|---|
| 5103 | + */ |
|---|
| 5104 | + |
|---|
| 5105 | +static int dsi_init_output(struct dsi_data *dsi) |
|---|
| 5106 | +{ |
|---|
| 5107 | + struct omap_dss_device *out = &dsi->output; |
|---|
| 5108 | + int r; |
|---|
| 5109 | + |
|---|
| 5110 | + out->dev = dsi->dev; |
|---|
| 5111 | + out->id = dsi->module_id == 0 ? |
|---|
| 5112 | + OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2; |
|---|
| 5113 | + |
|---|
| 5114 | + out->type = OMAP_DISPLAY_TYPE_DSI; |
|---|
| 5115 | + out->name = dsi->module_id == 0 ? "dsi.0" : "dsi.1"; |
|---|
| 5116 | + out->dispc_channel = dsi_get_channel(dsi); |
|---|
| 5117 | + out->ops = &dsi_ops; |
|---|
| 5118 | + out->owner = THIS_MODULE; |
|---|
| 5119 | + out->of_port = 0; |
|---|
| 5120 | + out->bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE |
|---|
| 5121 | + | DRM_BUS_FLAG_DE_HIGH |
|---|
| 5122 | + | DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE; |
|---|
| 5123 | + |
|---|
| 5124 | + r = omapdss_device_init_output(out, NULL); |
|---|
| 5125 | + if (r < 0) |
|---|
| 5126 | + return r; |
|---|
| 5127 | + |
|---|
| 5128 | + omapdss_device_register(out); |
|---|
| 5129 | + |
|---|
| 5130 | + return 0; |
|---|
| 5131 | +} |
|---|
| 5132 | + |
|---|
| 5133 | +static void dsi_uninit_output(struct dsi_data *dsi) |
|---|
| 5134 | +{ |
|---|
| 5135 | + struct omap_dss_device *out = &dsi->output; |
|---|
| 5136 | + |
|---|
| 5137 | + omapdss_device_unregister(out); |
|---|
| 5138 | + omapdss_device_cleanup_output(out); |
|---|
| 5139 | +} |
|---|
| 5140 | + |
|---|
| 5141 | +static int dsi_probe_of(struct dsi_data *dsi) |
|---|
| 5142 | +{ |
|---|
| 5143 | + struct device_node *node = dsi->dev->of_node; |
|---|
| 5144 | + struct property *prop; |
|---|
| 5145 | + u32 lane_arr[10]; |
|---|
| 5146 | + int len, num_pins; |
|---|
| 5147 | + int r, i; |
|---|
| 5148 | + struct device_node *ep; |
|---|
| 5149 | + struct omap_dsi_pin_config pin_cfg; |
|---|
| 5150 | + |
|---|
| 5151 | + ep = of_graph_get_endpoint_by_regs(node, 0, 0); |
|---|
| 5152 | + if (!ep) |
|---|
| 5153 | + return 0; |
|---|
| 5154 | + |
|---|
| 5155 | + prop = of_find_property(ep, "lanes", &len); |
|---|
| 5156 | + if (prop == NULL) { |
|---|
| 5157 | + dev_err(dsi->dev, "failed to find lane data\n"); |
|---|
| 5158 | + r = -EINVAL; |
|---|
| 5159 | + goto err; |
|---|
| 5160 | + } |
|---|
| 5161 | + |
|---|
| 5162 | + num_pins = len / sizeof(u32); |
|---|
| 5163 | + |
|---|
| 5164 | + if (num_pins < 4 || num_pins % 2 != 0 || |
|---|
| 5165 | + num_pins > dsi->num_lanes_supported * 2) { |
|---|
| 5166 | + dev_err(dsi->dev, "bad number of lanes\n"); |
|---|
| 5167 | + r = -EINVAL; |
|---|
| 5168 | + goto err; |
|---|
| 5169 | + } |
|---|
| 5170 | + |
|---|
| 5171 | + r = of_property_read_u32_array(ep, "lanes", lane_arr, num_pins); |
|---|
| 5172 | + if (r) { |
|---|
| 5173 | + dev_err(dsi->dev, "failed to read lane data\n"); |
|---|
| 5174 | + goto err; |
|---|
| 5175 | + } |
|---|
| 5176 | + |
|---|
| 5177 | + pin_cfg.num_pins = num_pins; |
|---|
| 5178 | + for (i = 0; i < num_pins; ++i) |
|---|
| 5179 | + pin_cfg.pins[i] = (int)lane_arr[i]; |
|---|
| 5180 | + |
|---|
| 5181 | + r = dsi_configure_pins(&dsi->output, &pin_cfg); |
|---|
| 5182 | + if (r) { |
|---|
| 5183 | + dev_err(dsi->dev, "failed to configure pins"); |
|---|
| 5184 | + goto err; |
|---|
| 5185 | + } |
|---|
| 5186 | + |
|---|
| 5187 | + of_node_put(ep); |
|---|
| 5188 | + |
|---|
| 5189 | + return 0; |
|---|
| 5190 | + |
|---|
| 5191 | +err: |
|---|
| 5192 | + of_node_put(ep); |
|---|
| 5193 | + return r; |
|---|
| 5194 | +} |
|---|
| 5195 | + |
|---|
| 5237 | 5196 | static const struct dsi_of_data dsi_of_data_omap34xx = { |
|---|
| 5238 | 5197 | .model = DSI_MODEL_OMAP3, |
|---|
| 5239 | 5198 | .pll_hw = &dss_omap3_dsi_pll_hw, |
|---|
| .. | .. |
|---|
| 5299 | 5258 | { /* sentinel */ } |
|---|
| 5300 | 5259 | }; |
|---|
| 5301 | 5260 | |
|---|
| 5302 | | -static int dsi_bind(struct device *dev, struct device *master, void *data) |
|---|
| 5261 | +static int dsi_probe(struct platform_device *pdev) |
|---|
| 5303 | 5262 | { |
|---|
| 5304 | | - struct platform_device *pdev = to_platform_device(dev); |
|---|
| 5305 | | - struct dss_device *dss = dss_get_device(master); |
|---|
| 5306 | 5263 | const struct soc_device_attribute *soc; |
|---|
| 5307 | 5264 | const struct dsi_module_id_data *d; |
|---|
| 5308 | | - u32 rev; |
|---|
| 5309 | | - int r, i; |
|---|
| 5265 | + struct device *dev = &pdev->dev; |
|---|
| 5310 | 5266 | struct dsi_data *dsi; |
|---|
| 5311 | 5267 | struct resource *dsi_mem; |
|---|
| 5312 | 5268 | struct resource *res; |
|---|
| 5269 | + unsigned int i; |
|---|
| 5270 | + int r; |
|---|
| 5313 | 5271 | |
|---|
| 5314 | 5272 | dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL); |
|---|
| 5315 | 5273 | if (!dsi) |
|---|
| 5316 | 5274 | return -ENOMEM; |
|---|
| 5317 | 5275 | |
|---|
| 5318 | | - dsi->dss = dss; |
|---|
| 5319 | 5276 | dsi->dev = dev; |
|---|
| 5320 | 5277 | dev_set_drvdata(dev, dsi); |
|---|
| 5321 | 5278 | |
|---|
| .. | .. |
|---|
| 5366 | 5323 | return r; |
|---|
| 5367 | 5324 | } |
|---|
| 5368 | 5325 | |
|---|
| 5326 | + dsi->vdds_dsi_reg = devm_regulator_get(dev, "vdd"); |
|---|
| 5327 | + if (IS_ERR(dsi->vdds_dsi_reg)) { |
|---|
| 5328 | + if (PTR_ERR(dsi->vdds_dsi_reg) != -EPROBE_DEFER) |
|---|
| 5329 | + DSSERR("can't get DSI VDD regulator\n"); |
|---|
| 5330 | + return PTR_ERR(dsi->vdds_dsi_reg); |
|---|
| 5331 | + } |
|---|
| 5332 | + |
|---|
| 5369 | 5333 | soc = soc_device_match(dsi_soc_devices); |
|---|
| 5370 | 5334 | if (soc) |
|---|
| 5371 | 5335 | dsi->data = soc->data; |
|---|
| .. | .. |
|---|
| 5412 | 5376 | if (r) |
|---|
| 5413 | 5377 | return r; |
|---|
| 5414 | 5378 | |
|---|
| 5415 | | - dsi_init_pll_data(dss, dsi); |
|---|
| 5416 | | - |
|---|
| 5417 | 5379 | 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 | 5380 | |
|---|
| 5427 | 5381 | /* DSI on OMAP3 doesn't have register DSI_GNQ, set number |
|---|
| 5428 | 5382 | * of data to 3 by default */ |
|---|
| 5429 | | - if (dsi->data->quirks & DSI_QUIRK_GNQ) |
|---|
| 5383 | + if (dsi->data->quirks & DSI_QUIRK_GNQ) { |
|---|
| 5384 | + dsi_runtime_get(dsi); |
|---|
| 5430 | 5385 | /* NB_DATA_LANES */ |
|---|
| 5431 | 5386 | dsi->num_lanes_supported = 1 + REG_GET(dsi, DSI_GNQ, 11, 9); |
|---|
| 5432 | | - else |
|---|
| 5387 | + dsi_runtime_put(dsi); |
|---|
| 5388 | + } else { |
|---|
| 5433 | 5389 | dsi->num_lanes_supported = 3; |
|---|
| 5390 | + } |
|---|
| 5434 | 5391 | |
|---|
| 5435 | | - dsi->line_buffer_size = dsi_get_line_buf_size(dsi); |
|---|
| 5392 | + r = of_platform_populate(dev->of_node, NULL, NULL, dev); |
|---|
| 5393 | + if (r) { |
|---|
| 5394 | + DSSERR("Failed to populate DSI child devices: %d\n", r); |
|---|
| 5395 | + goto err_pm_disable; |
|---|
| 5396 | + } |
|---|
| 5436 | 5397 | |
|---|
| 5437 | | - dsi_init_output(dsi); |
|---|
| 5398 | + r = dsi_init_output(dsi); |
|---|
| 5399 | + if (r) |
|---|
| 5400 | + goto err_of_depopulate; |
|---|
| 5438 | 5401 | |
|---|
| 5439 | 5402 | r = dsi_probe_of(dsi); |
|---|
| 5440 | 5403 | if (r) { |
|---|
| 5441 | 5404 | DSSERR("Invalid DSI DT data\n"); |
|---|
| 5442 | | - goto err_probe_of; |
|---|
| 5405 | + goto err_uninit_output; |
|---|
| 5443 | 5406 | } |
|---|
| 5444 | 5407 | |
|---|
| 5445 | | - r = of_platform_populate(dev->of_node, NULL, NULL, dev); |
|---|
| 5408 | + r = component_add(&pdev->dev, &dsi_component_ops); |
|---|
| 5446 | 5409 | 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 |
|---|
| 5410 | + goto err_uninit_output; |
|---|
| 5469 | 5411 | |
|---|
| 5470 | 5412 | return 0; |
|---|
| 5471 | 5413 | |
|---|
| 5472 | | -err_probe_of: |
|---|
| 5414 | +err_uninit_output: |
|---|
| 5473 | 5415 | dsi_uninit_output(dsi); |
|---|
| 5474 | | - dsi_runtime_put(dsi); |
|---|
| 5475 | | - |
|---|
| 5476 | | -err_runtime_get: |
|---|
| 5416 | +err_of_depopulate: |
|---|
| 5417 | + of_platform_depopulate(dev); |
|---|
| 5418 | +err_pm_disable: |
|---|
| 5477 | 5419 | pm_runtime_disable(dev); |
|---|
| 5478 | 5420 | return r; |
|---|
| 5479 | 5421 | } |
|---|
| 5480 | 5422 | |
|---|
| 5481 | | -static void dsi_unbind(struct device *dev, struct device *master, void *data) |
|---|
| 5423 | +static int dsi_remove(struct platform_device *pdev) |
|---|
| 5482 | 5424 | { |
|---|
| 5483 | | - struct dsi_data *dsi = dev_get_drvdata(dev); |
|---|
| 5425 | + struct dsi_data *dsi = platform_get_drvdata(pdev); |
|---|
| 5484 | 5426 | |
|---|
| 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); |
|---|
| 5427 | + component_del(&pdev->dev, &dsi_component_ops); |
|---|
| 5493 | 5428 | |
|---|
| 5494 | 5429 | dsi_uninit_output(dsi); |
|---|
| 5495 | 5430 | |
|---|
| 5496 | | - pm_runtime_disable(dev); |
|---|
| 5431 | + of_platform_depopulate(&pdev->dev); |
|---|
| 5432 | + |
|---|
| 5433 | + pm_runtime_disable(&pdev->dev); |
|---|
| 5497 | 5434 | |
|---|
| 5498 | 5435 | if (dsi->vdds_dsi_reg != NULL && dsi->vdds_dsi_enabled) { |
|---|
| 5499 | 5436 | regulator_disable(dsi->vdds_dsi_reg); |
|---|
| 5500 | 5437 | dsi->vdds_dsi_enabled = false; |
|---|
| 5501 | 5438 | } |
|---|
| 5502 | | -} |
|---|
| 5503 | 5439 | |
|---|
| 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 | 5440 | return 0; |
|---|
| 5518 | 5441 | } |
|---|
| 5519 | 5442 | |
|---|
| .. | .. |
|---|
| 5527 | 5450 | /* wait for current handler to finish before turning the DSI off */ |
|---|
| 5528 | 5451 | synchronize_irq(dsi->irq); |
|---|
| 5529 | 5452 | |
|---|
| 5530 | | - dispc_runtime_put(dsi->dss->dispc); |
|---|
| 5531 | | - |
|---|
| 5532 | 5453 | return 0; |
|---|
| 5533 | 5454 | } |
|---|
| 5534 | 5455 | |
|---|
| 5535 | 5456 | static int dsi_runtime_resume(struct device *dev) |
|---|
| 5536 | 5457 | { |
|---|
| 5537 | 5458 | 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 | 5459 | |
|---|
| 5544 | 5460 | dsi->is_enabled = true; |
|---|
| 5545 | 5461 | /* ensure the irq handler sees the is_enabled value */ |
|---|
| .. | .. |
|---|
| 5551 | 5467 | static const struct dev_pm_ops dsi_pm_ops = { |
|---|
| 5552 | 5468 | .runtime_suspend = dsi_runtime_suspend, |
|---|
| 5553 | 5469 | .runtime_resume = dsi_runtime_resume, |
|---|
| 5470 | + SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) |
|---|
| 5554 | 5471 | }; |
|---|
| 5555 | 5472 | |
|---|
| 5556 | 5473 | struct platform_driver omap_dsihw_driver = { |
|---|