mirror of https://gitee.com/openkylin/linux.git
Merge tag 'topic/drm-misc-2015-10-22' of git://anongit.freedesktop.org/drm-intel into drm-next
Few more drm-misc stragglers for 4.4. Big thing is the generic probe for imx/rockchip/armada (but the variant for msm/rpi/exynos is still missing). Also the hdmi clocking fixes from Ville which was a lot of confusion about which tree it should be applied to ;-) * tag 'topic/drm-misc-2015-10-22' of git://anongit.freedesktop.org/drm-intel: drm: correctly check failed allocation vga_switcheroo: Constify vga_switcheroo_handler drm/armada: Convert the probe function to the generic drm_of_component_probe() drm/rockchip: Convert the probe function to the generic drm_of_component_probe() drm/imx: Convert the probe function to the generic drm_of_component_probe() drm: Introduce generic probe function for component based masters. drm/edid: Round to closest when computing the CEA/HDMI alternate clock drm/edid: Fix up clock for CEA/HDMI modes specified via detailed timings
This commit is contained in:
commit
a76edb8cec
|
@ -501,7 +501,7 @@ static int amdgpu_atpx_get_client_id(struct pci_dev *pdev)
|
||||||
return VGA_SWITCHEROO_DIS;
|
return VGA_SWITCHEROO_DIS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct vga_switcheroo_handler amdgpu_atpx_handler = {
|
static const struct vga_switcheroo_handler amdgpu_atpx_handler = {
|
||||||
.switchto = amdgpu_atpx_switchto,
|
.switchto = amdgpu_atpx_switchto,
|
||||||
.power_state = amdgpu_atpx_power_state,
|
.power_state = amdgpu_atpx_power_state,
|
||||||
.init = amdgpu_atpx_init,
|
.init = amdgpu_atpx_init,
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <linux/of_graph.h>
|
#include <linux/of_graph.h>
|
||||||
#include <drm/drmP.h>
|
#include <drm/drmP.h>
|
||||||
#include <drm/drm_crtc_helper.h>
|
#include <drm/drm_crtc_helper.h>
|
||||||
|
#include <drm/drm_of.h>
|
||||||
#include "armada_crtc.h"
|
#include "armada_crtc.h"
|
||||||
#include "armada_drm.h"
|
#include "armada_drm.h"
|
||||||
#include "armada_gem.h"
|
#include "armada_gem.h"
|
||||||
|
@ -262,43 +263,29 @@ static void armada_add_endpoints(struct device *dev,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int armada_drm_find_components(struct device *dev,
|
static const struct component_master_ops armada_master_ops = {
|
||||||
struct component_match **match)
|
.bind = armada_drm_bind,
|
||||||
|
.unbind = armada_drm_unbind,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int armada_drm_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device_node *port;
|
struct component_match *match = NULL;
|
||||||
int i;
|
struct device *dev = &pdev->dev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (dev->of_node) {
|
ret = drm_of_component_probe(dev, compare_dev_name, &armada_master_ops);
|
||||||
struct device_node *np = dev->of_node;
|
if (ret != -EINVAL)
|
||||||
|
return ret;
|
||||||
|
|
||||||
for (i = 0; ; i++) {
|
if (dev->platform_data) {
|
||||||
port = of_parse_phandle(np, "ports", i);
|
|
||||||
if (!port)
|
|
||||||
break;
|
|
||||||
|
|
||||||
component_match_add(dev, match, compare_of, port);
|
|
||||||
of_node_put(port);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == 0) {
|
|
||||||
dev_err(dev, "missing 'ports' property\n");
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; ; i++) {
|
|
||||||
port = of_parse_phandle(np, "ports", i);
|
|
||||||
if (!port)
|
|
||||||
break;
|
|
||||||
|
|
||||||
armada_add_endpoints(dev, match, port);
|
|
||||||
of_node_put(port);
|
|
||||||
}
|
|
||||||
} else if (dev->platform_data) {
|
|
||||||
char **devices = dev->platform_data;
|
char **devices = dev->platform_data;
|
||||||
|
struct device_node *port;
|
||||||
struct device *d;
|
struct device *d;
|
||||||
|
int i;
|
||||||
|
|
||||||
for (i = 0; devices[i]; i++)
|
for (i = 0; devices[i]; i++)
|
||||||
component_match_add(dev, match, compare_dev_name,
|
component_match_add(dev, &match, compare_dev_name,
|
||||||
devices[i]);
|
devices[i]);
|
||||||
|
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
|
@ -308,32 +295,15 @@ static int armada_drm_find_components(struct device *dev,
|
||||||
|
|
||||||
for (i = 0; devices[i]; i++) {
|
for (i = 0; devices[i]; i++) {
|
||||||
d = bus_find_device_by_name(&platform_bus_type, NULL,
|
d = bus_find_device_by_name(&platform_bus_type, NULL,
|
||||||
devices[i]);
|
devices[i]);
|
||||||
if (d && d->of_node) {
|
if (d && d->of_node) {
|
||||||
for_each_child_of_node(d->of_node, port)
|
for_each_child_of_node(d->of_node, port)
|
||||||
armada_add_endpoints(dev, match, port);
|
armada_add_endpoints(dev, &match, port);
|
||||||
}
|
}
|
||||||
put_device(d);
|
put_device(d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct component_master_ops armada_master_ops = {
|
|
||||||
.bind = armada_drm_bind,
|
|
||||||
.unbind = armada_drm_unbind,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int armada_drm_probe(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
struct component_match *match = NULL;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = armada_drm_find_components(&pdev->dev, &match);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return component_master_add_with_match(&pdev->dev, &armada_master_ops,
|
return component_master_add_with_match(&pdev->dev, &armada_master_ops,
|
||||||
match);
|
match);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1533,6 +1533,9 @@ int drm_mode_create_tv_properties(struct drm_device *dev,
|
||||||
"select subconnector",
|
"select subconnector",
|
||||||
drm_tv_select_enum_list,
|
drm_tv_select_enum_list,
|
||||||
ARRAY_SIZE(drm_tv_select_enum_list));
|
ARRAY_SIZE(drm_tv_select_enum_list));
|
||||||
|
if (!tv_selector)
|
||||||
|
goto nomem;
|
||||||
|
|
||||||
dev->mode_config.tv_select_subconnector_property = tv_selector;
|
dev->mode_config.tv_select_subconnector_property = tv_selector;
|
||||||
|
|
||||||
tv_subconnector =
|
tv_subconnector =
|
||||||
|
@ -1540,6 +1543,8 @@ int drm_mode_create_tv_properties(struct drm_device *dev,
|
||||||
"subconnector",
|
"subconnector",
|
||||||
drm_tv_subconnector_enum_list,
|
drm_tv_subconnector_enum_list,
|
||||||
ARRAY_SIZE(drm_tv_subconnector_enum_list));
|
ARRAY_SIZE(drm_tv_subconnector_enum_list));
|
||||||
|
if (!tv_subconnector)
|
||||||
|
goto nomem;
|
||||||
dev->mode_config.tv_subconnector_property = tv_subconnector;
|
dev->mode_config.tv_subconnector_property = tv_subconnector;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1547,42 +1552,67 @@ int drm_mode_create_tv_properties(struct drm_device *dev,
|
||||||
*/
|
*/
|
||||||
dev->mode_config.tv_left_margin_property =
|
dev->mode_config.tv_left_margin_property =
|
||||||
drm_property_create_range(dev, 0, "left margin", 0, 100);
|
drm_property_create_range(dev, 0, "left margin", 0, 100);
|
||||||
|
if (!dev->mode_config.tv_left_margin_property)
|
||||||
|
goto nomem;
|
||||||
|
|
||||||
dev->mode_config.tv_right_margin_property =
|
dev->mode_config.tv_right_margin_property =
|
||||||
drm_property_create_range(dev, 0, "right margin", 0, 100);
|
drm_property_create_range(dev, 0, "right margin", 0, 100);
|
||||||
|
if (!dev->mode_config.tv_right_margin_property)
|
||||||
|
goto nomem;
|
||||||
|
|
||||||
dev->mode_config.tv_top_margin_property =
|
dev->mode_config.tv_top_margin_property =
|
||||||
drm_property_create_range(dev, 0, "top margin", 0, 100);
|
drm_property_create_range(dev, 0, "top margin", 0, 100);
|
||||||
|
if (!dev->mode_config.tv_top_margin_property)
|
||||||
|
goto nomem;
|
||||||
|
|
||||||
dev->mode_config.tv_bottom_margin_property =
|
dev->mode_config.tv_bottom_margin_property =
|
||||||
drm_property_create_range(dev, 0, "bottom margin", 0, 100);
|
drm_property_create_range(dev, 0, "bottom margin", 0, 100);
|
||||||
|
if (!dev->mode_config.tv_bottom_margin_property)
|
||||||
|
goto nomem;
|
||||||
|
|
||||||
dev->mode_config.tv_mode_property =
|
dev->mode_config.tv_mode_property =
|
||||||
drm_property_create(dev, DRM_MODE_PROP_ENUM,
|
drm_property_create(dev, DRM_MODE_PROP_ENUM,
|
||||||
"mode", num_modes);
|
"mode", num_modes);
|
||||||
|
if (!dev->mode_config.tv_mode_property)
|
||||||
|
goto nomem;
|
||||||
|
|
||||||
for (i = 0; i < num_modes; i++)
|
for (i = 0; i < num_modes; i++)
|
||||||
drm_property_add_enum(dev->mode_config.tv_mode_property, i,
|
drm_property_add_enum(dev->mode_config.tv_mode_property, i,
|
||||||
i, modes[i]);
|
i, modes[i]);
|
||||||
|
|
||||||
dev->mode_config.tv_brightness_property =
|
dev->mode_config.tv_brightness_property =
|
||||||
drm_property_create_range(dev, 0, "brightness", 0, 100);
|
drm_property_create_range(dev, 0, "brightness", 0, 100);
|
||||||
|
if (!dev->mode_config.tv_brightness_property)
|
||||||
|
goto nomem;
|
||||||
|
|
||||||
dev->mode_config.tv_contrast_property =
|
dev->mode_config.tv_contrast_property =
|
||||||
drm_property_create_range(dev, 0, "contrast", 0, 100);
|
drm_property_create_range(dev, 0, "contrast", 0, 100);
|
||||||
|
if (!dev->mode_config.tv_contrast_property)
|
||||||
|
goto nomem;
|
||||||
|
|
||||||
dev->mode_config.tv_flicker_reduction_property =
|
dev->mode_config.tv_flicker_reduction_property =
|
||||||
drm_property_create_range(dev, 0, "flicker reduction", 0, 100);
|
drm_property_create_range(dev, 0, "flicker reduction", 0, 100);
|
||||||
|
if (!dev->mode_config.tv_flicker_reduction_property)
|
||||||
|
goto nomem;
|
||||||
|
|
||||||
dev->mode_config.tv_overscan_property =
|
dev->mode_config.tv_overscan_property =
|
||||||
drm_property_create_range(dev, 0, "overscan", 0, 100);
|
drm_property_create_range(dev, 0, "overscan", 0, 100);
|
||||||
|
if (!dev->mode_config.tv_overscan_property)
|
||||||
|
goto nomem;
|
||||||
|
|
||||||
dev->mode_config.tv_saturation_property =
|
dev->mode_config.tv_saturation_property =
|
||||||
drm_property_create_range(dev, 0, "saturation", 0, 100);
|
drm_property_create_range(dev, 0, "saturation", 0, 100);
|
||||||
|
if (!dev->mode_config.tv_saturation_property)
|
||||||
|
goto nomem;
|
||||||
|
|
||||||
dev->mode_config.tv_hue_property =
|
dev->mode_config.tv_hue_property =
|
||||||
drm_property_create_range(dev, 0, "hue", 0, 100);
|
drm_property_create_range(dev, 0, "hue", 0, 100);
|
||||||
|
if (!dev->mode_config.tv_hue_property)
|
||||||
|
goto nomem;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
nomem:
|
||||||
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_mode_create_tv_properties);
|
EXPORT_SYMBOL(drm_mode_create_tv_properties);
|
||||||
|
|
||||||
|
|
|
@ -2418,6 +2418,8 @@ add_cvt_modes(struct drm_connector *connector, struct edid *edid)
|
||||||
return closure.modes;
|
return closure.modes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
do_detailed_mode(struct detailed_timing *timing, void *c)
|
do_detailed_mode(struct detailed_timing *timing, void *c)
|
||||||
{
|
{
|
||||||
|
@ -2434,6 +2436,13 @@ do_detailed_mode(struct detailed_timing *timing, void *c)
|
||||||
if (closure->preferred)
|
if (closure->preferred)
|
||||||
newmode->type |= DRM_MODE_TYPE_PREFERRED;
|
newmode->type |= DRM_MODE_TYPE_PREFERRED;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Detailed modes are limited to 10kHz pixel clock resolution,
|
||||||
|
* so fix up anything that looks like CEA/HDMI mode, but the clock
|
||||||
|
* is just slightly off.
|
||||||
|
*/
|
||||||
|
fixup_detailed_cea_mode_clock(newmode);
|
||||||
|
|
||||||
drm_mode_probed_add(closure->connector, newmode);
|
drm_mode_probed_add(closure->connector, newmode);
|
||||||
closure->modes++;
|
closure->modes++;
|
||||||
closure->preferred = 0;
|
closure->preferred = 0;
|
||||||
|
@ -2529,9 +2538,9 @@ cea_mode_alternate_clock(const struct drm_display_mode *cea_mode)
|
||||||
* and the 60Hz variant otherwise.
|
* and the 60Hz variant otherwise.
|
||||||
*/
|
*/
|
||||||
if (cea_mode->vdisplay == 240 || cea_mode->vdisplay == 480)
|
if (cea_mode->vdisplay == 240 || cea_mode->vdisplay == 480)
|
||||||
clock = clock * 1001 / 1000;
|
clock = DIV_ROUND_CLOSEST(clock * 1001, 1000);
|
||||||
else
|
else
|
||||||
clock = DIV_ROUND_UP(clock * 1000, 1001);
|
clock = DIV_ROUND_CLOSEST(clock * 1000, 1001);
|
||||||
|
|
||||||
return clock;
|
return clock;
|
||||||
}
|
}
|
||||||
|
@ -3103,6 +3112,45 @@ add_cea_modes(struct drm_connector *connector, struct edid *edid)
|
||||||
return modes;
|
return modes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode)
|
||||||
|
{
|
||||||
|
const struct drm_display_mode *cea_mode;
|
||||||
|
int clock1, clock2, clock;
|
||||||
|
u8 mode_idx;
|
||||||
|
const char *type;
|
||||||
|
|
||||||
|
mode_idx = drm_match_cea_mode(mode) - 1;
|
||||||
|
if (mode_idx < ARRAY_SIZE(edid_cea_modes)) {
|
||||||
|
type = "CEA";
|
||||||
|
cea_mode = &edid_cea_modes[mode_idx];
|
||||||
|
clock1 = cea_mode->clock;
|
||||||
|
clock2 = cea_mode_alternate_clock(cea_mode);
|
||||||
|
} else {
|
||||||
|
mode_idx = drm_match_hdmi_mode(mode) - 1;
|
||||||
|
if (mode_idx < ARRAY_SIZE(edid_4k_modes)) {
|
||||||
|
type = "HDMI";
|
||||||
|
cea_mode = &edid_4k_modes[mode_idx];
|
||||||
|
clock1 = cea_mode->clock;
|
||||||
|
clock2 = hdmi_mode_alternate_clock(cea_mode);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pick whichever is closest */
|
||||||
|
if (abs(mode->clock - clock1) < abs(mode->clock - clock2))
|
||||||
|
clock = clock1;
|
||||||
|
else
|
||||||
|
clock = clock2;
|
||||||
|
|
||||||
|
if (mode->clock == clock)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DRM_DEBUG("detailed mode matches %s VIC %d, adjusting clock %d -> %d\n",
|
||||||
|
type, mode_idx + 1, mode->clock, clock);
|
||||||
|
mode->clock = clock;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
parse_hdmi_vsdb(struct drm_connector *connector, const u8 *db)
|
parse_hdmi_vsdb(struct drm_connector *connector, const u8 *db)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <linux/component.h>
|
||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/of_graph.h>
|
#include <linux/of_graph.h>
|
||||||
|
@ -61,3 +62,90 @@ uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
|
||||||
return possible_crtcs;
|
return possible_crtcs;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_of_find_possible_crtcs);
|
EXPORT_SYMBOL(drm_of_find_possible_crtcs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_of_component_probe - Generic probe function for a component based master
|
||||||
|
* @dev: master device containing the OF node
|
||||||
|
* @compare_of: compare function used for matching components
|
||||||
|
* @master_ops: component master ops to be used
|
||||||
|
*
|
||||||
|
* Parse the platform device OF node and bind all the components associated
|
||||||
|
* with the master. Interface ports are added before the encoders in order to
|
||||||
|
* satisfy their .bind requirements
|
||||||
|
* See Documentation/devicetree/bindings/graph.txt for the bindings.
|
||||||
|
*
|
||||||
|
* Returns zero if successful, or one of the standard error codes if it fails.
|
||||||
|
*/
|
||||||
|
int drm_of_component_probe(struct device *dev,
|
||||||
|
int (*compare_of)(struct device *, void *),
|
||||||
|
const struct component_master_ops *m_ops)
|
||||||
|
{
|
||||||
|
struct device_node *ep, *port, *remote;
|
||||||
|
struct component_match *match = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!dev->of_node)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bind the crtc's ports first, so that drm_of_find_possible_crtcs()
|
||||||
|
* called from encoder's .bind callbacks works as expected
|
||||||
|
*/
|
||||||
|
for (i = 0; ; i++) {
|
||||||
|
port = of_parse_phandle(dev->of_node, "ports", i);
|
||||||
|
if (!port)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!of_device_is_available(port->parent)) {
|
||||||
|
of_node_put(port);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
component_match_add(dev, &match, compare_of, port);
|
||||||
|
of_node_put(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
dev_err(dev, "missing 'ports' property\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!match) {
|
||||||
|
dev_err(dev, "no available port\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For bound crtcs, bind the encoders attached to their remote endpoint
|
||||||
|
*/
|
||||||
|
for (i = 0; ; i++) {
|
||||||
|
port = of_parse_phandle(dev->of_node, "ports", i);
|
||||||
|
if (!port)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!of_device_is_available(port->parent)) {
|
||||||
|
of_node_put(port);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for_each_child_of_node(port, ep) {
|
||||||
|
remote = of_graph_get_remote_port_parent(ep);
|
||||||
|
if (!remote || !of_device_is_available(remote)) {
|
||||||
|
of_node_put(remote);
|
||||||
|
continue;
|
||||||
|
} else if (!of_device_is_available(remote->parent)) {
|
||||||
|
dev_warn(dev, "parent device of %s is not available\n",
|
||||||
|
remote->full_name);
|
||||||
|
of_node_put(remote);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
component_match_add(dev, &match, compare_of, remote);
|
||||||
|
of_node_put(remote);
|
||||||
|
}
|
||||||
|
of_node_put(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
return component_master_add_with_match(dev, m_ops, match);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_of_component_probe);
|
||||||
|
|
|
@ -531,59 +531,12 @@ static const struct component_master_ops imx_drm_ops = {
|
||||||
|
|
||||||
static int imx_drm_platform_probe(struct platform_device *pdev)
|
static int imx_drm_platform_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device_node *ep, *port, *remote;
|
int ret = drm_of_component_probe(&pdev->dev, compare_of, &imx_drm_ops);
|
||||||
struct component_match *match = NULL;
|
|
||||||
int ret;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/*
|
if (!ret)
|
||||||
* Bind the IPU display interface ports first, so that
|
ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
|
||||||
* imx_drm_encoder_parse_of called from encoder .bind callbacks
|
|
||||||
* works as expected.
|
|
||||||
*/
|
|
||||||
for (i = 0; ; i++) {
|
|
||||||
port = of_parse_phandle(pdev->dev.of_node, "ports", i);
|
|
||||||
if (!port)
|
|
||||||
break;
|
|
||||||
|
|
||||||
component_match_add(&pdev->dev, &match, compare_of, port);
|
return ret;
|
||||||
}
|
|
||||||
|
|
||||||
if (i == 0) {
|
|
||||||
dev_err(&pdev->dev, "missing 'ports' property\n");
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Then bind all encoders */
|
|
||||||
for (i = 0; ; i++) {
|
|
||||||
port = of_parse_phandle(pdev->dev.of_node, "ports", i);
|
|
||||||
if (!port)
|
|
||||||
break;
|
|
||||||
|
|
||||||
for_each_child_of_node(port, ep) {
|
|
||||||
remote = of_graph_get_remote_port_parent(ep);
|
|
||||||
if (!remote || !of_device_is_available(remote)) {
|
|
||||||
of_node_put(remote);
|
|
||||||
continue;
|
|
||||||
} else if (!of_device_is_available(remote->parent)) {
|
|
||||||
dev_warn(&pdev->dev, "parent device of %s is not available\n",
|
|
||||||
remote->full_name);
|
|
||||||
of_node_put(remote);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
component_match_add(&pdev->dev, &match, compare_of,
|
|
||||||
remote);
|
|
||||||
of_node_put(remote);
|
|
||||||
}
|
|
||||||
of_node_put(port);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return component_master_add_with_match(&pdev->dev, &imx_drm_ops, match);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int imx_drm_platform_remove(struct platform_device *pdev)
|
static int imx_drm_platform_remove(struct platform_device *pdev)
|
||||||
|
|
|
@ -206,7 +206,7 @@ static int nouveau_dsm_get_client_id(struct pci_dev *pdev)
|
||||||
return VGA_SWITCHEROO_DIS;
|
return VGA_SWITCHEROO_DIS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct vga_switcheroo_handler nouveau_dsm_handler = {
|
static const struct vga_switcheroo_handler nouveau_dsm_handler = {
|
||||||
.switchto = nouveau_dsm_switchto,
|
.switchto = nouveau_dsm_switchto,
|
||||||
.power_state = nouveau_dsm_power_state,
|
.power_state = nouveau_dsm_power_state,
|
||||||
.get_client_id = nouveau_dsm_get_client_id,
|
.get_client_id = nouveau_dsm_get_client_id,
|
||||||
|
|
|
@ -499,7 +499,7 @@ static int radeon_atpx_get_client_id(struct pci_dev *pdev)
|
||||||
return VGA_SWITCHEROO_DIS;
|
return VGA_SWITCHEROO_DIS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct vga_switcheroo_handler radeon_atpx_handler = {
|
static const struct vga_switcheroo_handler radeon_atpx_handler = {
|
||||||
.switchto = radeon_atpx_switchto,
|
.switchto = radeon_atpx_switchto,
|
||||||
.power_state = radeon_atpx_power_state,
|
.power_state = radeon_atpx_power_state,
|
||||||
.init = radeon_atpx_init,
|
.init = radeon_atpx_init,
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <drm/drmP.h>
|
#include <drm/drmP.h>
|
||||||
#include <drm/drm_crtc_helper.h>
|
#include <drm/drm_crtc_helper.h>
|
||||||
#include <drm/drm_fb_helper.h>
|
#include <drm/drm_fb_helper.h>
|
||||||
|
#include <drm/drm_of.h>
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
@ -418,29 +419,6 @@ static int compare_of(struct device *dev, void *data)
|
||||||
return dev->of_node == np;
|
return dev->of_node == np;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rockchip_add_endpoints(struct device *dev,
|
|
||||||
struct component_match **match,
|
|
||||||
struct device_node *port)
|
|
||||||
{
|
|
||||||
struct device_node *ep, *remote;
|
|
||||||
|
|
||||||
for_each_child_of_node(port, ep) {
|
|
||||||
remote = of_graph_get_remote_port_parent(ep);
|
|
||||||
if (!remote || !of_device_is_available(remote)) {
|
|
||||||
of_node_put(remote);
|
|
||||||
continue;
|
|
||||||
} else if (!of_device_is_available(remote->parent)) {
|
|
||||||
dev_warn(dev, "parent device of %s is not available\n",
|
|
||||||
remote->full_name);
|
|
||||||
of_node_put(remote);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
component_match_add(dev, match, compare_of, remote);
|
|
||||||
of_node_put(remote);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int rockchip_drm_bind(struct device *dev)
|
static int rockchip_drm_bind(struct device *dev)
|
||||||
{
|
{
|
||||||
struct drm_device *drm;
|
struct drm_device *drm;
|
||||||
|
@ -483,61 +461,14 @@ static const struct component_master_ops rockchip_drm_ops = {
|
||||||
|
|
||||||
static int rockchip_drm_platform_probe(struct platform_device *pdev)
|
static int rockchip_drm_platform_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device *dev = &pdev->dev;
|
int ret = drm_of_component_probe(&pdev->dev, compare_of,
|
||||||
struct component_match *match = NULL;
|
&rockchip_drm_ops);
|
||||||
struct device_node *np = dev->of_node;
|
|
||||||
struct device_node *port;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!np)
|
/* keep compatibility with old code that was returning -ENODEV */
|
||||||
|
if (ret == -EINVAL)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
/*
|
|
||||||
* Bind the crtc ports first, so that
|
|
||||||
* drm_of_find_possible_crtcs called from encoder .bind callbacks
|
|
||||||
* works as expected.
|
|
||||||
*/
|
|
||||||
for (i = 0;; i++) {
|
|
||||||
port = of_parse_phandle(np, "ports", i);
|
|
||||||
if (!port)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!of_device_is_available(port->parent)) {
|
return ret;
|
||||||
of_node_put(port);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
component_match_add(dev, &match, compare_of, port->parent);
|
|
||||||
of_node_put(port);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == 0) {
|
|
||||||
dev_err(dev, "missing 'ports' property\n");
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!match) {
|
|
||||||
dev_err(dev, "No available vop found for display-subsystem.\n");
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* For each bound crtc, bind the encoders attached to its
|
|
||||||
* remote endpoint.
|
|
||||||
*/
|
|
||||||
for (i = 0;; i++) {
|
|
||||||
port = of_parse_phandle(np, "ports", i);
|
|
||||||
if (!port)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!of_device_is_available(port->parent)) {
|
|
||||||
of_node_put(port);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
rockchip_add_endpoints(dev, &match, port);
|
|
||||||
of_node_put(port);
|
|
||||||
}
|
|
||||||
|
|
||||||
return component_master_add_with_match(dev, &rockchip_drm_ops, match);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rockchip_drm_platform_remove(struct platform_device *pdev)
|
static int rockchip_drm_platform_remove(struct platform_device *pdev)
|
||||||
|
|
|
@ -140,7 +140,7 @@ struct vgasr_priv {
|
||||||
int registered_clients;
|
int registered_clients;
|
||||||
struct list_head clients;
|
struct list_head clients;
|
||||||
|
|
||||||
struct vga_switcheroo_handler *handler;
|
const struct vga_switcheroo_handler *handler;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ID_BIT_AUDIO 0x100
|
#define ID_BIT_AUDIO 0x100
|
||||||
|
@ -195,7 +195,7 @@ static void vga_switcheroo_enable(void)
|
||||||
*
|
*
|
||||||
* Return: 0 on success, -EINVAL if a handler was already registered.
|
* Return: 0 on success, -EINVAL if a handler was already registered.
|
||||||
*/
|
*/
|
||||||
int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler)
|
int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler)
|
||||||
{
|
{
|
||||||
mutex_lock(&vgasr_mutex);
|
mutex_lock(&vgasr_mutex);
|
||||||
if (vgasr_priv.handler) {
|
if (vgasr_priv.handler) {
|
||||||
|
|
|
@ -346,7 +346,7 @@ gmux_active_client(struct apple_gmux_data *gmux_data)
|
||||||
return VGA_SWITCHEROO_DIS;
|
return VGA_SWITCHEROO_DIS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct vga_switcheroo_handler gmux_handler = {
|
static const struct vga_switcheroo_handler gmux_handler = {
|
||||||
.switchto = gmux_switchto,
|
.switchto = gmux_switchto,
|
||||||
.power_state = gmux_set_power_state,
|
.power_state = gmux_set_power_state,
|
||||||
.get_client_id = gmux_get_client_id,
|
.get_client_id = gmux_get_client_id,
|
||||||
|
|
|
@ -1,18 +1,31 @@
|
||||||
#ifndef __DRM_OF_H__
|
#ifndef __DRM_OF_H__
|
||||||
#define __DRM_OF_H__
|
#define __DRM_OF_H__
|
||||||
|
|
||||||
|
struct component_master_ops;
|
||||||
|
struct device;
|
||||||
struct drm_device;
|
struct drm_device;
|
||||||
struct device_node;
|
struct device_node;
|
||||||
|
|
||||||
#ifdef CONFIG_OF
|
#ifdef CONFIG_OF
|
||||||
extern uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
|
extern uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
|
||||||
struct device_node *port);
|
struct device_node *port);
|
||||||
|
extern int drm_of_component_probe(struct device *dev,
|
||||||
|
int (*compare_of)(struct device *, void *),
|
||||||
|
const struct component_master_ops *m_ops);
|
||||||
#else
|
#else
|
||||||
static inline uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
|
static inline uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
|
||||||
struct device_node *port)
|
struct device_node *port)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
drm_of_component_probe(struct device *dev,
|
||||||
|
int (*compare_of)(struct device *, void *),
|
||||||
|
const struct component_master_ops *m_ops)
|
||||||
|
{
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __DRM_OF_H__ */
|
#endif /* __DRM_OF_H__ */
|
||||||
|
|
|
@ -137,7 +137,7 @@ int vga_switcheroo_register_audio_client(struct pci_dev *pdev,
|
||||||
void vga_switcheroo_client_fb_set(struct pci_dev *dev,
|
void vga_switcheroo_client_fb_set(struct pci_dev *dev,
|
||||||
struct fb_info *info);
|
struct fb_info *info);
|
||||||
|
|
||||||
int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler);
|
int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler);
|
||||||
void vga_switcheroo_unregister_handler(void);
|
void vga_switcheroo_unregister_handler(void);
|
||||||
|
|
||||||
int vga_switcheroo_process_delayed_switch(void);
|
int vga_switcheroo_process_delayed_switch(void);
|
||||||
|
@ -155,7 +155,7 @@ static inline void vga_switcheroo_unregister_client(struct pci_dev *dev) {}
|
||||||
static inline int vga_switcheroo_register_client(struct pci_dev *dev,
|
static inline int vga_switcheroo_register_client(struct pci_dev *dev,
|
||||||
const struct vga_switcheroo_client_ops *ops, bool driver_power_control) { return 0; }
|
const struct vga_switcheroo_client_ops *ops, bool driver_power_control) { return 0; }
|
||||||
static inline void vga_switcheroo_client_fb_set(struct pci_dev *dev, struct fb_info *info) {}
|
static inline void vga_switcheroo_client_fb_set(struct pci_dev *dev, struct fb_info *info) {}
|
||||||
static inline int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler) { return 0; }
|
static inline int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler) { return 0; }
|
||||||
static inline int vga_switcheroo_register_audio_client(struct pci_dev *pdev,
|
static inline int vga_switcheroo_register_audio_client(struct pci_dev *pdev,
|
||||||
const struct vga_switcheroo_client_ops *ops,
|
const struct vga_switcheroo_client_ops *ops,
|
||||||
enum vga_switcheroo_client_id id) { return 0; }
|
enum vga_switcheroo_client_id id) { return 0; }
|
||||||
|
|
Loading…
Reference in New Issue