Rev 6935 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 6935 | Rev 6937 | ||
---|---|---|---|
Line 19... | Line 19... | ||
19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE |
19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE |
20 | * OF THIS SOFTWARE. |
20 | * OF THIS SOFTWARE. |
21 | */ |
21 | */ |
Line 22... | Line 22... | ||
22 | 22 | ||
23 | #include |
- | |
24 | #include |
- | |
25 | #include |
- | |
26 | #include |
- | |
27 | #include |
23 | #include |
28 | #include |
24 | #include |
29 | #include |
25 | #include |
30 | #include |
26 | #include |
31 | #include |
27 | #include |
Line 672... | Line 668... | ||
672 | msg->path_msg = true; |
668 | msg->path_msg = true; |
673 | return 0; |
669 | return 0; |
674 | } |
670 | } |
Line 675... | Line 671... | ||
675 | 671 | ||
676 | static int build_allocate_payload(struct drm_dp_sideband_msg_tx *msg, int port_num, |
672 | static int build_allocate_payload(struct drm_dp_sideband_msg_tx *msg, int port_num, |
- | 673 | u8 vcpi, uint16_t pbn, |
|
- | 674 | u8 number_sdp_streams, |
|
677 | u8 vcpi, uint16_t pbn) |
675 | u8 *sdp_stream_sink) |
678 | { |
676 | { |
679 | struct drm_dp_sideband_msg_req_body req; |
677 | struct drm_dp_sideband_msg_req_body req; |
680 | memset(&req, 0, sizeof(req)); |
678 | memset(&req, 0, sizeof(req)); |
681 | req.req_type = DP_ALLOCATE_PAYLOAD; |
679 | req.req_type = DP_ALLOCATE_PAYLOAD; |
682 | req.u.allocate_payload.port_number = port_num; |
680 | req.u.allocate_payload.port_number = port_num; |
683 | req.u.allocate_payload.vcpi = vcpi; |
681 | req.u.allocate_payload.vcpi = vcpi; |
- | 682 | req.u.allocate_payload.pbn = pbn; |
|
- | 683 | req.u.allocate_payload.number_sdp_streams = number_sdp_streams; |
|
- | 684 | memcpy(req.u.allocate_payload.sdp_stream_sink, sdp_stream_sink, |
|
684 | req.u.allocate_payload.pbn = pbn; |
685 | number_sdp_streams); |
685 | drm_dp_encode_sideband_req(&req, msg); |
686 | drm_dp_encode_sideband_req(&req, msg); |
686 | msg->path_msg = true; |
687 | msg->path_msg = true; |
687 | return 0; |
688 | return 0; |
Line 914... | Line 915... | ||
914 | return; |
915 | return; |
915 | } |
916 | } |
916 | /* no need to clean up vcpi |
917 | /* no need to clean up vcpi |
917 | * as if we have no connector we never setup a vcpi */ |
918 | * as if we have no connector we never setup a vcpi */ |
918 | drm_dp_port_teardown_pdt(port, port->pdt); |
919 | drm_dp_port_teardown_pdt(port, port->pdt); |
919 | port->pdt = DP_PEER_DEVICE_NONE; |
- | |
920 | } |
920 | } |
921 | kfree(port); |
921 | kfree(port); |
922 | } |
922 | } |
Line 923... | Line 923... | ||
923 | 923 | ||
Line 1160... | Line 1160... | ||
1160 | mutex_unlock(&mstb->mgr->lock); |
1160 | mutex_unlock(&mstb->mgr->lock); |
1161 | /* drop port list reference */ |
1161 | /* drop port list reference */ |
1162 | drm_dp_put_port(port); |
1162 | drm_dp_put_port(port); |
1163 | goto out; |
1163 | goto out; |
1164 | } |
1164 | } |
1165 | if ((port->pdt == DP_PEER_DEVICE_DP_LEGACY_CONV || |
- | |
1166 | port->pdt == DP_PEER_DEVICE_SST_SINK) && |
- | |
1167 | port->port_num >= DP_MST_LOGICAL_PORT_0) { |
1165 | if (port->port_num >= DP_MST_LOGICAL_PORT_0) { |
1168 | port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc); |
1166 | port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc); |
1169 | drm_mode_connector_set_tile_property(port->connector); |
1167 | drm_mode_connector_set_tile_property(port->connector); |
1170 | } |
1168 | } |
1171 | (*mstb->mgr->cbs->register_connector)(port->connector); |
1169 | (*mstb->mgr->cbs->register_connector)(port->connector); |
1172 | } |
1170 | } |
Line 1672... | Line 1670... | ||
1672 | int pbn) |
1670 | int pbn) |
1673 | { |
1671 | { |
1674 | struct drm_dp_sideband_msg_tx *txmsg; |
1672 | struct drm_dp_sideband_msg_tx *txmsg; |
1675 | struct drm_dp_mst_branch *mstb; |
1673 | struct drm_dp_mst_branch *mstb; |
1676 | int len, ret, port_num; |
1674 | int len, ret, port_num; |
- | 1675 | u8 sinks[DRM_DP_MAX_SDP_STREAMS]; |
|
- | 1676 | int i; |
|
Line 1677... | Line 1677... | ||
1677 | 1677 | ||
1678 | port = drm_dp_get_validated_port_ref(mgr, port); |
1678 | port = drm_dp_get_validated_port_ref(mgr, port); |
1679 | if (!port) |
1679 | if (!port) |
Line 1694... | Line 1694... | ||
1694 | if (!txmsg) { |
1694 | if (!txmsg) { |
1695 | ret = -ENOMEM; |
1695 | ret = -ENOMEM; |
1696 | goto fail_put; |
1696 | goto fail_put; |
1697 | } |
1697 | } |
Line -... | Line 1698... | ||
- | 1698 | ||
- | 1699 | for (i = 0; i < port->num_sdp_streams; i++) |
|
- | 1700 | sinks[i] = i; |
|
1698 | 1701 | ||
1699 | txmsg->dst = mstb; |
1702 | txmsg->dst = mstb; |
1700 | len = build_allocate_payload(txmsg, port_num, |
1703 | len = build_allocate_payload(txmsg, port_num, |
1701 | id, |
1704 | id, |
Line 1702... | Line 1705... | ||
1702 | pbn); |
1705 | pbn, port->num_sdp_streams, sinks); |
Line 1703... | Line 1706... | ||
1703 | 1706 | ||
1704 | drm_dp_queue_down_tx(mgr, txmsg); |
1707 | drm_dp_queue_down_tx(mgr, txmsg); |
Line 1800... | Line 1803... | ||
1800 | if (!port) { |
1803 | if (!port) { |
1801 | mutex_unlock(&mgr->payload_lock); |
1804 | mutex_unlock(&mgr->payload_lock); |
1802 | return -EINVAL; |
1805 | return -EINVAL; |
1803 | } |
1806 | } |
1804 | req_payload.num_slots = mgr->proposed_vcpis[i]->num_slots; |
1807 | req_payload.num_slots = mgr->proposed_vcpis[i]->num_slots; |
- | 1808 | req_payload.vcpi = mgr->proposed_vcpis[i]->vcpi; |
|
1805 | } else { |
1809 | } else { |
1806 | port = NULL; |
1810 | port = NULL; |
1807 | req_payload.num_slots = 0; |
1811 | req_payload.num_slots = 0; |
1808 | } |
1812 | } |
Line 1815... | Line 1819... | ||
1815 | 1819 | ||
1816 | /* need to push an update for this payload */ |
1820 | /* need to push an update for this payload */ |
1817 | if (req_payload.num_slots) { |
1821 | if (req_payload.num_slots) { |
1818 | drm_dp_create_payload_step1(mgr, mgr->proposed_vcpis[i]->vcpi, &req_payload); |
1822 | drm_dp_create_payload_step1(mgr, mgr->proposed_vcpis[i]->vcpi, &req_payload); |
- | 1823 | mgr->payloads[i].num_slots = req_payload.num_slots; |
|
1819 | mgr->payloads[i].num_slots = req_payload.num_slots; |
1824 | mgr->payloads[i].vcpi = req_payload.vcpi; |
1820 | } else if (mgr->payloads[i].num_slots) { |
1825 | } else if (mgr->payloads[i].num_slots) { |
1821 | mgr->payloads[i].num_slots = 0; |
1826 | mgr->payloads[i].num_slots = 0; |
1822 | drm_dp_destroy_payload_step1(mgr, port, mgr->payloads[i].vcpi, &mgr->payloads[i]); |
1827 | drm_dp_destroy_payload_step1(mgr, port, port->vcpi.vcpi, &mgr->payloads[i]); |
1823 | req_payload.payload_state = mgr->payloads[i].payload_state; |
1828 | req_payload.payload_state = mgr->payloads[i].payload_state; |
1824 | mgr->payloads[i].start_slot = 0; |
1829 | mgr->payloads[i].start_slot = 0; |
1825 | } |
1830 | } |
1826 | mgr->payloads[i].payload_state = req_payload.payload_state; |
1831 | mgr->payloads[i].payload_state = req_payload.payload_state; |
Line 1953... | Line 1958... | ||
1953 | 1958 | ||
1954 | static int drm_dp_encode_up_ack_reply(struct drm_dp_sideband_msg_tx *msg, u8 req_type) |
1959 | static int drm_dp_encode_up_ack_reply(struct drm_dp_sideband_msg_tx *msg, u8 req_type) |
1955 | { |
1960 | { |
Line 1956... | Line 1961... | ||
1956 | struct drm_dp_sideband_msg_reply_body reply; |
1961 | struct drm_dp_sideband_msg_reply_body reply; |
1957 | 1962 | ||
1958 | reply.reply_type = 1; |
1963 | reply.reply_type = 0; |
1959 | reply.req_type = req_type; |
1964 | reply.req_type = req_type; |
1960 | drm_dp_encode_sideband_reply(&reply, msg); |
1965 | drm_dp_encode_sideband_reply(&reply, msg); |
Line 2409... | Line 2414... | ||
2409 | return status; |
2414 | return status; |
2410 | } |
2415 | } |
2411 | EXPORT_SYMBOL(drm_dp_mst_detect_port); |
2416 | EXPORT_SYMBOL(drm_dp_mst_detect_port); |
Line 2412... | Line 2417... | ||
2412 | 2417 | ||
- | 2418 | /** |
|
- | 2419 | * drm_dp_mst_port_has_audio() - Check whether port has audio capability or not |
|
- | 2420 | * @mgr: manager for this port |
|
- | 2421 | * @port: unverified pointer to a port. |
|
- | 2422 | * |
|
- | 2423 | * This returns whether the port supports audio or not. |
|
- | 2424 | */ |
|
- | 2425 | bool drm_dp_mst_port_has_audio(struct drm_dp_mst_topology_mgr *mgr, |
|
- | 2426 | struct drm_dp_mst_port *port) |
|
- | 2427 | { |
|
- | 2428 | bool ret = false; |
|
- | 2429 | ||
- | 2430 | port = drm_dp_get_validated_port_ref(mgr, port); |
|
- | 2431 | if (!port) |
|
- | 2432 | return ret; |
|
- | 2433 | ret = port->has_audio; |
|
- | 2434 | drm_dp_put_port(port); |
|
- | 2435 | return ret; |
|
- | 2436 | } |
|
- | 2437 | EXPORT_SYMBOL(drm_dp_mst_port_has_audio); |
|
- | 2438 | ||
2413 | /** |
2439 | /** |
2414 | * drm_dp_mst_get_edid() - get EDID for an MST port |
2440 | * drm_dp_mst_get_edid() - get EDID for an MST port |
2415 | * @connector: toplevel connector to get EDID for |
2441 | * @connector: toplevel connector to get EDID for |
2416 | * @mgr: manager for this port |
2442 | * @mgr: manager for this port |
2417 | * @port: unverified pointer to a port. |
2443 | * @port: unverified pointer to a port. |
Line 2433... | Line 2459... | ||
2433 | edid = drm_edid_duplicate(port->cached_edid); |
2459 | edid = drm_edid_duplicate(port->cached_edid); |
2434 | else { |
2460 | else { |
2435 | edid = drm_get_edid(connector, &port->aux.ddc); |
2461 | edid = drm_get_edid(connector, &port->aux.ddc); |
2436 | drm_mode_connector_set_tile_property(connector); |
2462 | drm_mode_connector_set_tile_property(connector); |
2437 | } |
2463 | } |
- | 2464 | port->has_audio = drm_detect_monitor_audio(edid); |
|
2438 | drm_dp_put_port(port); |
2465 | drm_dp_put_port(port); |
2439 | return edid; |
2466 | return edid; |
2440 | } |
2467 | } |
2441 | EXPORT_SYMBOL(drm_dp_mst_get_edid); |
2468 | EXPORT_SYMBOL(drm_dp_mst_get_edid); |
Line 2819... | Line 2846... | ||
2819 | mgr->dev = dev; |
2846 | mgr->dev = dev; |
2820 | mgr->aux = aux; |
2847 | mgr->aux = aux; |
2821 | mgr->max_dpcd_transaction_bytes = max_dpcd_transaction_bytes; |
2848 | mgr->max_dpcd_transaction_bytes = max_dpcd_transaction_bytes; |
2822 | mgr->max_payloads = max_payloads; |
2849 | mgr->max_payloads = max_payloads; |
2823 | mgr->conn_base_id = conn_base_id; |
2850 | mgr->conn_base_id = conn_base_id; |
- | 2851 | if (max_payloads + 1 > sizeof(mgr->payload_mask) * 8 || |
|
- | 2852 | max_payloads + 1 > sizeof(mgr->vcpi_mask) * 8) |
|
- | 2853 | return -EINVAL; |
|
2824 | mgr->payloads = kcalloc(max_payloads, sizeof(struct drm_dp_payload), GFP_KERNEL); |
2854 | mgr->payloads = kcalloc(max_payloads, sizeof(struct drm_dp_payload), GFP_KERNEL); |
2825 | if (!mgr->payloads) |
2855 | if (!mgr->payloads) |
2826 | return -ENOMEM; |
2856 | return -ENOMEM; |
2827 | mgr->proposed_vcpis = kcalloc(max_payloads, sizeof(struct drm_dp_vcpi *), GFP_KERNEL); |
2857 | mgr->proposed_vcpis = kcalloc(max_payloads, sizeof(struct drm_dp_vcpi *), GFP_KERNEL); |
2828 | if (!mgr->proposed_vcpis) |
2858 | if (!mgr->proposed_vcpis) |
2829 | return -ENOMEM; |
2859 | return -ENOMEM; |
2830 | set_bit(0, &mgr->payload_mask); |
2860 | set_bit(0, &mgr->payload_mask); |
2831 | test_calc_pbn_mode(); |
2861 | if (test_calc_pbn_mode() < 0) |
- | 2862 | DRM_ERROR("MST PBN self-test failed\n"); |
|
- | 2863 | ||
2832 | return 0; |
2864 | return 0; |
2833 | } |
2865 | } |
2834 | EXPORT_SYMBOL(drm_dp_mst_topology_mgr_init); |
2866 | EXPORT_SYMBOL(drm_dp_mst_topology_mgr_init); |
Line 2835... | Line 2867... | ||
2835 | 2867 |