| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Samsung SoC MIPI DSI Master driver. |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (c) 2014 Samsung Electronics Co., Ltd |
|---|
| 5 | 6 | * |
|---|
| 6 | 7 | * Contacts: Tomasz Figa <t.figa@samsung.com> |
|---|
| 7 | | - * |
|---|
| 8 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 9 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 10 | | - * published by the Free Software Foundation. |
|---|
| 11 | 8 | */ |
|---|
| 12 | 9 | |
|---|
| 13 | | -#include <asm/unaligned.h> |
|---|
| 14 | | - |
|---|
| 15 | | -#include <drm/drmP.h> |
|---|
| 16 | | -#include <drm/drm_crtc_helper.h> |
|---|
| 17 | | -#include <drm/drm_mipi_dsi.h> |
|---|
| 18 | | -#include <drm/drm_panel.h> |
|---|
| 19 | | -#include <drm/drm_atomic_helper.h> |
|---|
| 20 | | - |
|---|
| 21 | 10 | #include <linux/clk.h> |
|---|
| 11 | +#include <linux/delay.h> |
|---|
| 12 | +#include <linux/component.h> |
|---|
| 22 | 13 | #include <linux/gpio/consumer.h> |
|---|
| 23 | 14 | #include <linux/irq.h> |
|---|
| 24 | 15 | #include <linux/of_device.h> |
|---|
| .. | .. |
|---|
| 26 | 17 | #include <linux/of_graph.h> |
|---|
| 27 | 18 | #include <linux/phy/phy.h> |
|---|
| 28 | 19 | #include <linux/regulator/consumer.h> |
|---|
| 29 | | -#include <linux/component.h> |
|---|
| 20 | + |
|---|
| 21 | +#include <asm/unaligned.h> |
|---|
| 30 | 22 | |
|---|
| 31 | 23 | #include <video/mipi_display.h> |
|---|
| 32 | 24 | #include <video/videomode.h> |
|---|
| 25 | + |
|---|
| 26 | +#include <drm/drm_atomic_helper.h> |
|---|
| 27 | +#include <drm/drm_bridge.h> |
|---|
| 28 | +#include <drm/drm_fb_helper.h> |
|---|
| 29 | +#include <drm/drm_mipi_dsi.h> |
|---|
| 30 | +#include <drm/drm_panel.h> |
|---|
| 31 | +#include <drm/drm_print.h> |
|---|
| 32 | +#include <drm/drm_probe_helper.h> |
|---|
| 33 | +#include <drm/drm_simple_kms_helper.h> |
|---|
| 33 | 34 | |
|---|
| 34 | 35 | #include "exynos_drm_crtc.h" |
|---|
| 35 | 36 | #include "exynos_drm_drv.h" |
|---|
| .. | .. |
|---|
| 211 | 212 | |
|---|
| 212 | 213 | #define OLD_SCLK_MIPI_CLK_NAME "pll_clk" |
|---|
| 213 | 214 | |
|---|
| 214 | | -static char *clk_names[5] = { "bus_clk", "sclk_mipi", |
|---|
| 215 | +static const char *const clk_names[5] = { "bus_clk", "sclk_mipi", |
|---|
| 215 | 216 | "phyclk_mipidphy0_bitclkdiv8", "phyclk_mipidphy0_rxclkesc0", |
|---|
| 216 | 217 | "sclk_rgb_vclk_to_dsim0" }; |
|---|
| 217 | 218 | |
|---|
| .. | .. |
|---|
| 255 | 256 | struct mipi_dsi_host dsi_host; |
|---|
| 256 | 257 | struct drm_connector connector; |
|---|
| 257 | 258 | struct drm_panel *panel; |
|---|
| 259 | + struct list_head bridge_chain; |
|---|
| 260 | + struct drm_bridge *out_bridge; |
|---|
| 258 | 261 | struct device *dev; |
|---|
| 259 | 262 | |
|---|
| 260 | 263 | void __iomem *reg_base; |
|---|
| .. | .. |
|---|
| 279 | 282 | struct list_head transfer_list; |
|---|
| 280 | 283 | |
|---|
| 281 | 284 | const struct exynos_dsi_driver_data *driver_data; |
|---|
| 282 | | - struct device_node *bridge_node; |
|---|
| 285 | + struct device_node *in_bridge_node; |
|---|
| 283 | 286 | }; |
|---|
| 284 | 287 | |
|---|
| 285 | 288 | #define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host) |
|---|
| .. | .. |
|---|
| 544 | 547 | unsigned long best_freq = 0; |
|---|
| 545 | 548 | u32 min_delta = 0xffffffff; |
|---|
| 546 | 549 | u8 p_min, p_max; |
|---|
| 547 | | - u8 _p, uninitialized_var(best_p); |
|---|
| 548 | | - u16 _m, uninitialized_var(best_m); |
|---|
| 549 | | - u8 _s, uninitialized_var(best_s); |
|---|
| 550 | + u8 _p, best_p; |
|---|
| 551 | + u16 _m, best_m; |
|---|
| 552 | + u8 _s, best_s; |
|---|
| 550 | 553 | |
|---|
| 551 | 554 | p_min = DIV_ROUND_UP(fin, (12 * MHZ)); |
|---|
| 552 | 555 | p_max = fin / (6 * MHZ); |
|---|
| .. | .. |
|---|
| 984 | 987 | switch (length) { |
|---|
| 985 | 988 | case 3: |
|---|
| 986 | 989 | reg |= payload[2] << 16; |
|---|
| 987 | | - /* Fall through */ |
|---|
| 990 | + fallthrough; |
|---|
| 988 | 991 | case 2: |
|---|
| 989 | 992 | reg |= payload[1] << 8; |
|---|
| 990 | | - /* Fall through */ |
|---|
| 993 | + fallthrough; |
|---|
| 991 | 994 | case 1: |
|---|
| 992 | 995 | reg |= payload[0]; |
|---|
| 993 | 996 | exynos_dsi_write(dsi, DSIM_PAYLOAD_REG, reg); |
|---|
| .. | .. |
|---|
| 1035 | 1038 | payload[1] = reg >> 16; |
|---|
| 1036 | 1039 | ++xfer->rx_done; |
|---|
| 1037 | 1040 | } |
|---|
| 1038 | | - /* Fall through */ |
|---|
| 1041 | + fallthrough; |
|---|
| 1039 | 1042 | case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE: |
|---|
| 1040 | 1043 | case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE: |
|---|
| 1041 | 1044 | payload[0] = reg >> 8; |
|---|
| .. | .. |
|---|
| 1079 | 1082 | switch (length) { |
|---|
| 1080 | 1083 | case 3: |
|---|
| 1081 | 1084 | payload[2] = (reg >> 16) & 0xff; |
|---|
| 1082 | | - /* Fall through */ |
|---|
| 1085 | + fallthrough; |
|---|
| 1083 | 1086 | case 2: |
|---|
| 1084 | 1087 | payload[1] = (reg >> 8) & 0xff; |
|---|
| 1085 | | - /* Fall through */ |
|---|
| 1088 | + fallthrough; |
|---|
| 1086 | 1089 | case 1: |
|---|
| 1087 | 1090 | payload[0] = reg & 0xff; |
|---|
| 1088 | 1091 | } |
|---|
| .. | .. |
|---|
| 1376 | 1379 | static void exynos_dsi_enable(struct drm_encoder *encoder) |
|---|
| 1377 | 1380 | { |
|---|
| 1378 | 1381 | struct exynos_dsi *dsi = encoder_to_dsi(encoder); |
|---|
| 1382 | + struct drm_bridge *iter; |
|---|
| 1379 | 1383 | int ret; |
|---|
| 1380 | 1384 | |
|---|
| 1381 | 1385 | if (dsi->state & DSIM_STATE_ENABLED) |
|---|
| 1382 | 1386 | return; |
|---|
| 1383 | 1387 | |
|---|
| 1384 | 1388 | pm_runtime_get_sync(dsi->dev); |
|---|
| 1385 | | - |
|---|
| 1386 | 1389 | dsi->state |= DSIM_STATE_ENABLED; |
|---|
| 1387 | 1390 | |
|---|
| 1388 | | - ret = drm_panel_prepare(dsi->panel); |
|---|
| 1389 | | - if (ret < 0) { |
|---|
| 1390 | | - dsi->state &= ~DSIM_STATE_ENABLED; |
|---|
| 1391 | | - pm_runtime_put_sync(dsi->dev); |
|---|
| 1392 | | - return; |
|---|
| 1391 | + if (dsi->panel) { |
|---|
| 1392 | + ret = drm_panel_prepare(dsi->panel); |
|---|
| 1393 | + if (ret < 0) |
|---|
| 1394 | + goto err_put_sync; |
|---|
| 1395 | + } else { |
|---|
| 1396 | + list_for_each_entry_reverse(iter, &dsi->bridge_chain, |
|---|
| 1397 | + chain_node) { |
|---|
| 1398 | + if (iter->funcs->pre_enable) |
|---|
| 1399 | + iter->funcs->pre_enable(iter); |
|---|
| 1400 | + } |
|---|
| 1393 | 1401 | } |
|---|
| 1394 | 1402 | |
|---|
| 1395 | 1403 | exynos_dsi_set_display_mode(dsi); |
|---|
| 1396 | 1404 | exynos_dsi_set_display_enable(dsi, true); |
|---|
| 1397 | 1405 | |
|---|
| 1398 | | - ret = drm_panel_enable(dsi->panel); |
|---|
| 1399 | | - if (ret < 0) { |
|---|
| 1400 | | - dsi->state &= ~DSIM_STATE_ENABLED; |
|---|
| 1401 | | - exynos_dsi_set_display_enable(dsi, false); |
|---|
| 1402 | | - drm_panel_unprepare(dsi->panel); |
|---|
| 1403 | | - pm_runtime_put_sync(dsi->dev); |
|---|
| 1404 | | - return; |
|---|
| 1406 | + if (dsi->panel) { |
|---|
| 1407 | + ret = drm_panel_enable(dsi->panel); |
|---|
| 1408 | + if (ret < 0) |
|---|
| 1409 | + goto err_display_disable; |
|---|
| 1410 | + } else { |
|---|
| 1411 | + list_for_each_entry(iter, &dsi->bridge_chain, chain_node) { |
|---|
| 1412 | + if (iter->funcs->enable) |
|---|
| 1413 | + iter->funcs->enable(iter); |
|---|
| 1414 | + } |
|---|
| 1405 | 1415 | } |
|---|
| 1406 | 1416 | |
|---|
| 1407 | 1417 | dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE; |
|---|
| 1418 | + return; |
|---|
| 1419 | + |
|---|
| 1420 | +err_display_disable: |
|---|
| 1421 | + exynos_dsi_set_display_enable(dsi, false); |
|---|
| 1422 | + drm_panel_unprepare(dsi->panel); |
|---|
| 1423 | + |
|---|
| 1424 | +err_put_sync: |
|---|
| 1425 | + dsi->state &= ~DSIM_STATE_ENABLED; |
|---|
| 1426 | + pm_runtime_put(dsi->dev); |
|---|
| 1408 | 1427 | } |
|---|
| 1409 | 1428 | |
|---|
| 1410 | 1429 | static void exynos_dsi_disable(struct drm_encoder *encoder) |
|---|
| 1411 | 1430 | { |
|---|
| 1412 | 1431 | struct exynos_dsi *dsi = encoder_to_dsi(encoder); |
|---|
| 1432 | + struct drm_bridge *iter; |
|---|
| 1413 | 1433 | |
|---|
| 1414 | 1434 | if (!(dsi->state & DSIM_STATE_ENABLED)) |
|---|
| 1415 | 1435 | return; |
|---|
| .. | .. |
|---|
| 1417 | 1437 | dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE; |
|---|
| 1418 | 1438 | |
|---|
| 1419 | 1439 | drm_panel_disable(dsi->panel); |
|---|
| 1440 | + |
|---|
| 1441 | + list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) { |
|---|
| 1442 | + if (iter->funcs->disable) |
|---|
| 1443 | + iter->funcs->disable(iter); |
|---|
| 1444 | + } |
|---|
| 1445 | + |
|---|
| 1420 | 1446 | exynos_dsi_set_display_enable(dsi, false); |
|---|
| 1421 | 1447 | drm_panel_unprepare(dsi->panel); |
|---|
| 1422 | 1448 | |
|---|
| 1423 | | - dsi->state &= ~DSIM_STATE_ENABLED; |
|---|
| 1449 | + list_for_each_entry(iter, &dsi->bridge_chain, chain_node) { |
|---|
| 1450 | + if (iter->funcs->post_disable) |
|---|
| 1451 | + iter->funcs->post_disable(iter); |
|---|
| 1452 | + } |
|---|
| 1424 | 1453 | |
|---|
| 1454 | + dsi->state &= ~DSIM_STATE_ENABLED; |
|---|
| 1425 | 1455 | pm_runtime_put_sync(dsi->dev); |
|---|
| 1426 | 1456 | } |
|---|
| 1427 | 1457 | |
|---|
| .. | .. |
|---|
| 1452 | 1482 | struct exynos_dsi *dsi = connector_to_dsi(connector); |
|---|
| 1453 | 1483 | |
|---|
| 1454 | 1484 | if (dsi->panel) |
|---|
| 1455 | | - return dsi->panel->funcs->get_modes(dsi->panel); |
|---|
| 1485 | + return drm_panel_get_modes(dsi->panel, connector); |
|---|
| 1456 | 1486 | |
|---|
| 1457 | 1487 | return 0; |
|---|
| 1458 | 1488 | } |
|---|
| .. | .. |
|---|
| 1465 | 1495 | { |
|---|
| 1466 | 1496 | struct exynos_dsi *dsi = encoder_to_dsi(encoder); |
|---|
| 1467 | 1497 | struct drm_connector *connector = &dsi->connector; |
|---|
| 1498 | + struct drm_device *drm = encoder->dev; |
|---|
| 1468 | 1499 | int ret; |
|---|
| 1469 | 1500 | |
|---|
| 1470 | 1501 | connector->polled = DRM_CONNECTOR_POLL_HPD; |
|---|
| 1471 | 1502 | |
|---|
| 1472 | | - ret = drm_connector_init(encoder->dev, connector, |
|---|
| 1473 | | - &exynos_dsi_connector_funcs, |
|---|
| 1503 | + ret = drm_connector_init(drm, connector, &exynos_dsi_connector_funcs, |
|---|
| 1474 | 1504 | DRM_MODE_CONNECTOR_DSI); |
|---|
| 1475 | 1505 | if (ret) { |
|---|
| 1476 | | - DRM_ERROR("Failed to initialize connector with drm\n"); |
|---|
| 1506 | + DRM_DEV_ERROR(dsi->dev, |
|---|
| 1507 | + "Failed to initialize connector with drm\n"); |
|---|
| 1477 | 1508 | return ret; |
|---|
| 1478 | 1509 | } |
|---|
| 1479 | 1510 | |
|---|
| 1480 | 1511 | connector->status = connector_status_disconnected; |
|---|
| 1481 | 1512 | drm_connector_helper_add(connector, &exynos_dsi_connector_helper_funcs); |
|---|
| 1482 | 1513 | drm_connector_attach_encoder(connector, encoder); |
|---|
| 1514 | + if (!drm->registered) |
|---|
| 1515 | + return 0; |
|---|
| 1483 | 1516 | |
|---|
| 1517 | + connector->funcs->reset(connector); |
|---|
| 1518 | + drm_connector_register(connector); |
|---|
| 1484 | 1519 | return 0; |
|---|
| 1485 | 1520 | } |
|---|
| 1486 | 1521 | |
|---|
| .. | .. |
|---|
| 1489 | 1524 | .disable = exynos_dsi_disable, |
|---|
| 1490 | 1525 | }; |
|---|
| 1491 | 1526 | |
|---|
| 1492 | | -static const struct drm_encoder_funcs exynos_dsi_encoder_funcs = { |
|---|
| 1493 | | - .destroy = drm_encoder_cleanup, |
|---|
| 1494 | | -}; |
|---|
| 1495 | | - |
|---|
| 1496 | 1527 | MODULE_DEVICE_TABLE(of, exynos_dsi_of_match); |
|---|
| 1497 | 1528 | |
|---|
| 1498 | 1529 | static int exynos_dsi_host_attach(struct mipi_dsi_host *host, |
|---|
| 1499 | 1530 | struct mipi_dsi_device *device) |
|---|
| 1500 | 1531 | { |
|---|
| 1501 | 1532 | struct exynos_dsi *dsi = host_to_dsi(host); |
|---|
| 1502 | | - struct drm_device *drm = dsi->connector.dev; |
|---|
| 1533 | + struct drm_encoder *encoder = &dsi->encoder; |
|---|
| 1534 | + struct drm_device *drm = encoder->dev; |
|---|
| 1535 | + struct drm_bridge *out_bridge; |
|---|
| 1536 | + |
|---|
| 1537 | + out_bridge = of_drm_find_bridge(device->dev.of_node); |
|---|
| 1538 | + if (out_bridge) { |
|---|
| 1539 | + drm_bridge_attach(encoder, out_bridge, NULL, 0); |
|---|
| 1540 | + dsi->out_bridge = out_bridge; |
|---|
| 1541 | + list_splice_init(&encoder->bridge_chain, &dsi->bridge_chain); |
|---|
| 1542 | + } else { |
|---|
| 1543 | + int ret = exynos_dsi_create_connector(encoder); |
|---|
| 1544 | + |
|---|
| 1545 | + if (ret) { |
|---|
| 1546 | + DRM_DEV_ERROR(dsi->dev, |
|---|
| 1547 | + "failed to create connector ret = %d\n", |
|---|
| 1548 | + ret); |
|---|
| 1549 | + drm_encoder_cleanup(encoder); |
|---|
| 1550 | + return ret; |
|---|
| 1551 | + } |
|---|
| 1552 | + |
|---|
| 1553 | + dsi->panel = of_drm_find_panel(device->dev.of_node); |
|---|
| 1554 | + if (IS_ERR(dsi->panel)) |
|---|
| 1555 | + dsi->panel = NULL; |
|---|
| 1556 | + else |
|---|
| 1557 | + dsi->connector.status = connector_status_connected; |
|---|
| 1558 | + } |
|---|
| 1503 | 1559 | |
|---|
| 1504 | 1560 | /* |
|---|
| 1505 | 1561 | * This is a temporary solution and should be made by more generic way. |
|---|
| .. | .. |
|---|
| 1518 | 1574 | dsi->lanes = device->lanes; |
|---|
| 1519 | 1575 | dsi->format = device->format; |
|---|
| 1520 | 1576 | dsi->mode_flags = device->mode_flags; |
|---|
| 1521 | | - dsi->panel = of_drm_find_panel(device->dev.of_node); |
|---|
| 1522 | | - if (IS_ERR(dsi->panel)) |
|---|
| 1523 | | - dsi->panel = NULL; |
|---|
| 1524 | | - |
|---|
| 1525 | | - if (dsi->panel) { |
|---|
| 1526 | | - drm_panel_attach(dsi->panel, &dsi->connector); |
|---|
| 1527 | | - dsi->connector.status = connector_status_connected; |
|---|
| 1528 | | - } |
|---|
| 1529 | 1577 | exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode = |
|---|
| 1530 | 1578 | !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO); |
|---|
| 1531 | 1579 | |
|---|
| .. | .. |
|---|
| 1541 | 1589 | struct mipi_dsi_device *device) |
|---|
| 1542 | 1590 | { |
|---|
| 1543 | 1591 | struct exynos_dsi *dsi = host_to_dsi(host); |
|---|
| 1544 | | - struct drm_device *drm = dsi->connector.dev; |
|---|
| 1545 | | - |
|---|
| 1546 | | - mutex_lock(&drm->mode_config.mutex); |
|---|
| 1592 | + struct drm_device *drm = dsi->encoder.dev; |
|---|
| 1547 | 1593 | |
|---|
| 1548 | 1594 | if (dsi->panel) { |
|---|
| 1595 | + mutex_lock(&drm->mode_config.mutex); |
|---|
| 1549 | 1596 | exynos_dsi_disable(&dsi->encoder); |
|---|
| 1550 | | - drm_panel_detach(dsi->panel); |
|---|
| 1551 | 1597 | dsi->panel = NULL; |
|---|
| 1552 | 1598 | dsi->connector.status = connector_status_disconnected; |
|---|
| 1599 | + mutex_unlock(&drm->mode_config.mutex); |
|---|
| 1600 | + } else { |
|---|
| 1601 | + if (dsi->out_bridge->funcs->detach) |
|---|
| 1602 | + dsi->out_bridge->funcs->detach(dsi->out_bridge); |
|---|
| 1603 | + dsi->out_bridge = NULL; |
|---|
| 1604 | + INIT_LIST_HEAD(&dsi->bridge_chain); |
|---|
| 1553 | 1605 | } |
|---|
| 1554 | | - |
|---|
| 1555 | | - mutex_unlock(&drm->mode_config.mutex); |
|---|
| 1556 | 1606 | |
|---|
| 1557 | 1607 | if (drm->mode_config.poll_enabled) |
|---|
| 1558 | 1608 | drm_kms_helper_hotplug_event(drm); |
|---|
| .. | .. |
|---|
| 1634 | 1684 | if (ret < 0) |
|---|
| 1635 | 1685 | return ret; |
|---|
| 1636 | 1686 | |
|---|
| 1637 | | - dsi->bridge_node = of_graph_get_remote_node(node, DSI_PORT_IN, 0); |
|---|
| 1687 | + dsi->in_bridge_node = of_graph_get_remote_node(node, DSI_PORT_IN, 0); |
|---|
| 1638 | 1688 | |
|---|
| 1639 | 1689 | return 0; |
|---|
| 1640 | 1690 | } |
|---|
| .. | .. |
|---|
| 1645 | 1695 | struct drm_encoder *encoder = dev_get_drvdata(dev); |
|---|
| 1646 | 1696 | struct exynos_dsi *dsi = encoder_to_dsi(encoder); |
|---|
| 1647 | 1697 | struct drm_device *drm_dev = data; |
|---|
| 1648 | | - struct drm_bridge *bridge; |
|---|
| 1698 | + struct drm_bridge *in_bridge; |
|---|
| 1649 | 1699 | int ret; |
|---|
| 1650 | 1700 | |
|---|
| 1651 | | - drm_encoder_init(drm_dev, encoder, &exynos_dsi_encoder_funcs, |
|---|
| 1652 | | - DRM_MODE_ENCODER_TMDS, NULL); |
|---|
| 1701 | + drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_TMDS); |
|---|
| 1653 | 1702 | |
|---|
| 1654 | 1703 | drm_encoder_helper_add(encoder, &exynos_dsi_encoder_helper_funcs); |
|---|
| 1655 | 1704 | |
|---|
| .. | .. |
|---|
| 1657 | 1706 | if (ret < 0) |
|---|
| 1658 | 1707 | return ret; |
|---|
| 1659 | 1708 | |
|---|
| 1660 | | - ret = exynos_dsi_create_connector(encoder); |
|---|
| 1661 | | - if (ret) { |
|---|
| 1662 | | - DRM_ERROR("failed to create connector ret = %d\n", ret); |
|---|
| 1663 | | - drm_encoder_cleanup(encoder); |
|---|
| 1664 | | - return ret; |
|---|
| 1665 | | - } |
|---|
| 1666 | | - |
|---|
| 1667 | | - if (dsi->bridge_node) { |
|---|
| 1668 | | - bridge = of_drm_find_bridge(dsi->bridge_node); |
|---|
| 1669 | | - if (bridge) |
|---|
| 1670 | | - drm_bridge_attach(encoder, bridge, NULL); |
|---|
| 1709 | + if (dsi->in_bridge_node) { |
|---|
| 1710 | + in_bridge = of_drm_find_bridge(dsi->in_bridge_node); |
|---|
| 1711 | + if (in_bridge) |
|---|
| 1712 | + drm_bridge_attach(encoder, in_bridge, NULL, 0); |
|---|
| 1671 | 1713 | } |
|---|
| 1672 | 1714 | |
|---|
| 1673 | 1715 | return mipi_dsi_host_register(&dsi->dsi_host); |
|---|
| .. | .. |
|---|
| 1706 | 1748 | init_completion(&dsi->completed); |
|---|
| 1707 | 1749 | spin_lock_init(&dsi->transfer_lock); |
|---|
| 1708 | 1750 | INIT_LIST_HEAD(&dsi->transfer_list); |
|---|
| 1751 | + INIT_LIST_HEAD(&dsi->bridge_chain); |
|---|
| 1709 | 1752 | |
|---|
| 1710 | 1753 | dsi->dsi_host.ops = &exynos_dsi_ops; |
|---|
| 1711 | 1754 | dsi->dsi_host.dev = dev; |
|---|
| .. | .. |
|---|
| 1713 | 1756 | dsi->dev = dev; |
|---|
| 1714 | 1757 | dsi->driver_data = of_device_get_match_data(dev); |
|---|
| 1715 | 1758 | |
|---|
| 1716 | | - ret = exynos_dsi_parse_dt(dsi); |
|---|
| 1717 | | - if (ret) |
|---|
| 1718 | | - return ret; |
|---|
| 1719 | | - |
|---|
| 1720 | 1759 | dsi->supplies[0].supply = "vddcore"; |
|---|
| 1721 | 1760 | dsi->supplies[1].supply = "vddio"; |
|---|
| 1722 | 1761 | ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(dsi->supplies), |
|---|
| 1723 | 1762 | dsi->supplies); |
|---|
| 1724 | | - if (ret) { |
|---|
| 1725 | | - if (ret != -EPROBE_DEFER) |
|---|
| 1726 | | - dev_info(dev, "failed to get regulators: %d\n", ret); |
|---|
| 1727 | | - return ret; |
|---|
| 1728 | | - } |
|---|
| 1763 | + if (ret) |
|---|
| 1764 | + return dev_err_probe(dev, ret, "failed to get regulators\n"); |
|---|
| 1729 | 1765 | |
|---|
| 1730 | 1766 | dsi->clks = devm_kcalloc(dev, |
|---|
| 1731 | 1767 | dsi->driver_data->num_clks, sizeof(*dsi->clks), |
|---|
| .. | .. |
|---|
| 1763 | 1799 | } |
|---|
| 1764 | 1800 | |
|---|
| 1765 | 1801 | dsi->irq = platform_get_irq(pdev, 0); |
|---|
| 1766 | | - if (dsi->irq < 0) { |
|---|
| 1767 | | - dev_err(dev, "failed to request dsi irq resource\n"); |
|---|
| 1802 | + if (dsi->irq < 0) |
|---|
| 1768 | 1803 | return dsi->irq; |
|---|
| 1769 | | - } |
|---|
| 1770 | 1804 | |
|---|
| 1771 | 1805 | irq_set_status_flags(dsi->irq, IRQ_NOAUTOEN); |
|---|
| 1772 | 1806 | ret = devm_request_threaded_irq(dev, dsi->irq, NULL, |
|---|
| .. | .. |
|---|
| 1777 | 1811 | return ret; |
|---|
| 1778 | 1812 | } |
|---|
| 1779 | 1813 | |
|---|
| 1814 | + ret = exynos_dsi_parse_dt(dsi); |
|---|
| 1815 | + if (ret) |
|---|
| 1816 | + return ret; |
|---|
| 1817 | + |
|---|
| 1780 | 1818 | platform_set_drvdata(pdev, &dsi->encoder); |
|---|
| 1781 | 1819 | |
|---|
| 1782 | 1820 | pm_runtime_enable(dev); |
|---|
| 1783 | 1821 | |
|---|
| 1784 | | - return component_add(dev, &exynos_dsi_component_ops); |
|---|
| 1822 | + ret = component_add(dev, &exynos_dsi_component_ops); |
|---|
| 1823 | + if (ret) |
|---|
| 1824 | + goto err_disable_runtime; |
|---|
| 1825 | + |
|---|
| 1826 | + return 0; |
|---|
| 1827 | + |
|---|
| 1828 | +err_disable_runtime: |
|---|
| 1829 | + pm_runtime_disable(dev); |
|---|
| 1830 | + of_node_put(dsi->in_bridge_node); |
|---|
| 1831 | + |
|---|
| 1832 | + return ret; |
|---|
| 1785 | 1833 | } |
|---|
| 1786 | 1834 | |
|---|
| 1787 | 1835 | static int exynos_dsi_remove(struct platform_device *pdev) |
|---|
| 1788 | 1836 | { |
|---|
| 1789 | 1837 | struct exynos_dsi *dsi = platform_get_drvdata(pdev); |
|---|
| 1790 | 1838 | |
|---|
| 1791 | | - of_node_put(dsi->bridge_node); |
|---|
| 1839 | + of_node_put(dsi->in_bridge_node); |
|---|
| 1792 | 1840 | |
|---|
| 1793 | 1841 | pm_runtime_disable(&pdev->dev); |
|---|
| 1794 | 1842 | |
|---|