aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/drm_connector.c44
-rw-r--r--include/drm/drm_modes.h13
2 files changed, 50 insertions, 7 deletions
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index dfc8ca1e9413..9b9ba5d5ec0c 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1531,8 +1531,10 @@ static struct drm_encoder *drm_connector_get_encoder(struct drm_connector *conne
1531 return connector->encoder; 1531 return connector->encoder;
1532} 1532}
1533 1533
1534static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode, 1534static bool
1535 const struct drm_file *file_priv) 1535drm_mode_expose_to_userspace(const struct drm_display_mode *mode,
1536 const struct list_head *export_list,
1537 const struct drm_file *file_priv)
1536{ 1538{
1537 /* 1539 /*
1538 * If user-space hasn't configured the driver to expose the stereo 3D 1540 * If user-space hasn't configured the driver to expose the stereo 3D
@@ -1540,6 +1542,23 @@ static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode,
1540 */ 1542 */
1541 if (!file_priv->stereo_allowed && drm_mode_is_stereo(mode)) 1543 if (!file_priv->stereo_allowed && drm_mode_is_stereo(mode))
1542 return false; 1544 return false;
1545 /*
1546 * If user-space hasn't configured the driver to expose the modes
1547 * with aspect-ratio, don't expose them. However if such a mode
1548 * is unique, let it be exposed, but reset the aspect-ratio flags
1549 * while preparing the list of user-modes.
1550 */
1551 if (!file_priv->aspect_ratio_allowed) {
1552 struct drm_display_mode *mode_itr;
1553
1554 list_for_each_entry(mode_itr, export_list, export_head)
1555 if (drm_mode_match(mode_itr, mode,
1556 DRM_MODE_MATCH_TIMINGS |
1557 DRM_MODE_MATCH_CLOCK |
1558 DRM_MODE_MATCH_FLAGS |
1559 DRM_MODE_MATCH_3D_FLAGS))
1560 return false;
1561 }
1543 1562
1544 return true; 1563 return true;
1545} 1564}
@@ -1559,6 +1578,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
1559 struct drm_mode_modeinfo u_mode; 1578 struct drm_mode_modeinfo u_mode;
1560 struct drm_mode_modeinfo __user *mode_ptr; 1579 struct drm_mode_modeinfo __user *mode_ptr;
1561 uint32_t __user *encoder_ptr; 1580 uint32_t __user *encoder_ptr;
1581 LIST_HEAD(export_list);
1562 1582
1563 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1583 if (!drm_core_check_feature(dev, DRIVER_MODESET))
1564 return -EINVAL; 1584 return -EINVAL;
@@ -1607,21 +1627,31 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
1607 1627
1608 /* delayed so we get modes regardless of pre-fill_modes state */ 1628 /* delayed so we get modes regardless of pre-fill_modes state */
1609 list_for_each_entry(mode, &connector->modes, head) 1629 list_for_each_entry(mode, &connector->modes, head)
1610 if (drm_mode_expose_to_userspace(mode, file_priv)) 1630 if (drm_mode_expose_to_userspace(mode, &export_list,
1631 file_priv)) {
1632 list_add_tail(&mode->export_head, &export_list);
1611 mode_count++; 1633 mode_count++;
1634 }
1612 1635
1613 /* 1636 /*
1614 * This ioctl is called twice, once to determine how much space is 1637 * This ioctl is called twice, once to determine how much space is
1615 * needed, and the 2nd time to fill it. 1638 * needed, and the 2nd time to fill it.
1639 * The modes that need to be exposed to the user are maintained in the
1640 * 'export_list'. When the ioctl is called first time to determine the,
1641 * space, the export_list gets filled, to find the no.of modes. In the
1642 * 2nd time, the user modes are filled, one by one from the export_list.
1616 */ 1643 */
1617 if ((out_resp->count_modes >= mode_count) && mode_count) { 1644 if ((out_resp->count_modes >= mode_count) && mode_count) {
1618 copied = 0; 1645 copied = 0;
1619 mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr; 1646 mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr;
1620 list_for_each_entry(mode, &connector->modes, head) { 1647 list_for_each_entry(mode, &export_list, export_head) {
1621 if (!drm_mode_expose_to_userspace(mode, file_priv))
1622 continue;
1623
1624 drm_mode_convert_to_umode(&u_mode, mode); 1648 drm_mode_convert_to_umode(&u_mode, mode);
1649 /*
1650 * Reset aspect ratio flags of user-mode, if modes with
1651 * aspect-ratio are not supported.
1652 */
1653 if (!file_priv->aspect_ratio_allowed)
1654 u_mode.flags &= ~DRM_MODE_FLAG_PIC_AR_MASK;
1625 if (copy_to_user(mode_ptr + copied, 1655 if (copy_to_user(mode_ptr + copied,
1626 &u_mode, sizeof(u_mode))) { 1656 &u_mode, sizeof(u_mode))) {
1627 ret = -EFAULT; 1657 ret = -EFAULT;
diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
index 2f78b7ee4824..b159fe07fcf9 100644
--- a/include/drm/drm_modes.h
+++ b/include/drm/drm_modes.h
@@ -411,6 +411,19 @@ struct drm_display_mode {
411 * Field for setting the HDMI picture aspect ratio of a mode. 411 * Field for setting the HDMI picture aspect ratio of a mode.
412 */ 412 */
413 enum hdmi_picture_aspect picture_aspect_ratio; 413 enum hdmi_picture_aspect picture_aspect_ratio;
414
415 /**
416 * @export_head:
417 *
418 * struct list_head for modes to be exposed to the userspace.
419 * This is to maintain a list of exposed modes while preparing
420 * user-mode's list in drm_mode_getconnector ioctl. The purpose of this
421 * list_head only lies in the ioctl function, and is not expected to be
422 * used outside the function.
423 * Once used, the stale pointers are not reset, but left as it is, to
424 * avoid overhead of protecting it by mode_config.mutex.
425 */
426 struct list_head export_head;
414}; 427};
415 428
416/** 429/**