diff options
| author | Thierry Reding <treding@nvidia.com> | 2014-01-09 11:08:36 -0500 |
|---|---|---|
| committer | Thierry Reding <treding@nvidia.com> | 2014-01-23 09:51:32 -0500 |
| commit | 13411ddd319057ae334a4084ebcf2c741b317f34 (patch) | |
| tree | 9915698fb7fe169acd53b9b7f75347524ed04a98 | |
| parent | 70bf6878a874523e4b62992d07b5739298f8c1eb (diff) | |
drm/tegra: Obtain head number from DT
The head number of a given display controller is fixed in hardware and
required to program outputs appropriately. Relying on the driver probe
order to determine this number will not work, since that could yield a
situation where the second head was probed first and would be assigned
head number 0 instead of 1.
By explicitly specifying the head number in the device tree, it is no
longer necessary to rely on these assumptions. As a fallback, if the
property isn't available, derive the head number from the display
controller node's position in the device tree. That's somewhat more
reliable than the previous default but not a proper solution.
Tested-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
| -rw-r--r-- | Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/tegra/dc.c | 41 |
2 files changed, 42 insertions, 2 deletions
diff --git a/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt b/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt index 9e9008f8fa32..efaeec8961b6 100644 --- a/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt +++ b/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt | |||
| @@ -118,6 +118,9 @@ of the following host1x client modules: | |||
| 118 | See ../reset/reset.txt for details. | 118 | See ../reset/reset.txt for details. |
| 119 | - reset-names: Must include the following entries: | 119 | - reset-names: Must include the following entries: |
| 120 | - dc | 120 | - dc |
| 121 | - nvidia,head: The number of the display controller head. This is used to | ||
| 122 | setup the various types of output to receive video data from the given | ||
| 123 | head. | ||
| 121 | 124 | ||
| 122 | Each display controller node has a child node, named "rgb", that represents | 125 | Each display controller node has a child node, named "rgb", that represents |
| 123 | the RGB output associated with the controller. It can take the following | 126 | the RGB output associated with the controller. It can take the following |
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 386f3b4b0094..9336006b475d 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c | |||
| @@ -1100,8 +1100,6 @@ static int tegra_dc_init(struct host1x_client *client) | |||
| 1100 | struct tegra_dc *dc = host1x_client_to_dc(client); | 1100 | struct tegra_dc *dc = host1x_client_to_dc(client); |
| 1101 | int err; | 1101 | int err; |
| 1102 | 1102 | ||
| 1103 | dc->pipe = tegra->drm->mode_config.num_crtc; | ||
| 1104 | |||
| 1105 | drm_crtc_init(tegra->drm, &dc->base, &tegra_crtc_funcs); | 1103 | drm_crtc_init(tegra->drm, &dc->base, &tegra_crtc_funcs); |
| 1106 | drm_mode_crtc_set_gamma_size(&dc->base, 256); | 1104 | drm_mode_crtc_set_gamma_size(&dc->base, 256); |
| 1107 | drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs); | 1105 | drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs); |
| @@ -1187,6 +1185,41 @@ static const struct of_device_id tegra_dc_of_match[] = { | |||
| 1187 | } | 1185 | } |
| 1188 | }; | 1186 | }; |
| 1189 | 1187 | ||
| 1188 | static int tegra_dc_parse_dt(struct tegra_dc *dc) | ||
| 1189 | { | ||
| 1190 | struct device_node *np; | ||
| 1191 | u32 value = 0; | ||
| 1192 | int err; | ||
| 1193 | |||
| 1194 | err = of_property_read_u32(dc->dev->of_node, "nvidia,head", &value); | ||
| 1195 | if (err < 0) { | ||
| 1196 | dev_err(dc->dev, "missing \"nvidia,head\" property\n"); | ||
| 1197 | |||
| 1198 | /* | ||
| 1199 | * If the nvidia,head property isn't present, try to find the | ||
| 1200 | * correct head number by looking up the position of this | ||
| 1201 | * display controller's node within the device tree. Assuming | ||
| 1202 | * that the nodes are ordered properly in the DTS file and | ||
| 1203 | * that the translation into a flattened device tree blob | ||
| 1204 | * preserves that ordering this will actually yield the right | ||
| 1205 | * head number. | ||
| 1206 | * | ||
| 1207 | * If those assumptions don't hold, this will still work for | ||
| 1208 | * cases where only a single display controller is used. | ||
| 1209 | */ | ||
| 1210 | for_each_matching_node(np, tegra_dc_of_match) { | ||
| 1211 | if (np == dc->dev->of_node) | ||
| 1212 | break; | ||
| 1213 | |||
| 1214 | value++; | ||
| 1215 | } | ||
| 1216 | } | ||
| 1217 | |||
| 1218 | dc->pipe = value; | ||
| 1219 | |||
| 1220 | return 0; | ||
| 1221 | } | ||
| 1222 | |||
| 1190 | static int tegra_dc_probe(struct platform_device *pdev) | 1223 | static int tegra_dc_probe(struct platform_device *pdev) |
| 1191 | { | 1224 | { |
| 1192 | const struct of_device_id *id; | 1225 | const struct of_device_id *id; |
| @@ -1207,6 +1240,10 @@ static int tegra_dc_probe(struct platform_device *pdev) | |||
| 1207 | dc->dev = &pdev->dev; | 1240 | dc->dev = &pdev->dev; |
| 1208 | dc->soc = id->data; | 1241 | dc->soc = id->data; |
| 1209 | 1242 | ||
| 1243 | err = tegra_dc_parse_dt(dc); | ||
| 1244 | if (err < 0) | ||
| 1245 | return err; | ||
| 1246 | |||
| 1210 | dc->clk = devm_clk_get(&pdev->dev, NULL); | 1247 | dc->clk = devm_clk_get(&pdev->dev, NULL); |
| 1211 | if (IS_ERR(dc->clk)) { | 1248 | if (IS_ERR(dc->clk)) { |
| 1212 | dev_err(&pdev->dev, "failed to get clock\n"); | 1249 | dev_err(&pdev->dev, "failed to get clock\n"); |
