Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'drm/tegra/for-3.15-rc1' of git://anongit.freedesktop.org/tegra/linux into drm-next

drm/tegra: Changes for v3.15-rc1

Implement eDP support for Tegra124 and support the PRIME vmap()/vunmap()
operations.

A symbol that is required for upcoming V4L2 support is now exported by
the host1x driver.

Relicense drivers under the GPL v2 for consistency. One exception is the
public header file, which is relicensed under MIT to abide by the common
rule.

* tag 'drm/tegra/for-3.15-rc1' of git://anongit.freedesktop.org/tegra/linux:
drm/tegra: Use standard GPL v2 license text
drm/tegra: Relicense under GPL v2
drm/tegra: Relicense public header under MIT
drm/tegra: Add eDP support
gpu: host1x: export host1x_syncpt_incr_max() function
drm/tegra: prime: Add vmap support

+2129 -109
+42
Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
··· 190 190 - nvidia,edid: supplies a binary EDID blob 191 191 - nvidia,panel: phandle of a display panel 192 192 193 + - sor: serial output resource 194 + 195 + Required properties: 196 + - compatible: "nvidia,tegra124-sor" 197 + - reg: Physical base address and length of the controller's registers. 198 + - interrupts: The interrupt outputs from the controller. 199 + - clocks: Must contain an entry for each entry in clock-names. 200 + See ../clocks/clock-bindings.txt for details. 201 + - clock-names: Must include the following entries: 202 + - sor: clock input for the SOR hardware 203 + - parent: input for the pixel clock 204 + - dp: reference clock for the SOR clock 205 + - safe: safe reference for the SOR clock during power up 206 + - resets: Must contain an entry for each entry in reset-names. 207 + See ../reset/reset.txt for details. 208 + - reset-names: Must include the following entries: 209 + - sor 210 + 211 + Optional properties: 212 + - nvidia,ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing 213 + - nvidia,hpd-gpio: specifies a GPIO used for hotplug detection 214 + - nvidia,edid: supplies a binary EDID blob 215 + - nvidia,panel: phandle of a display panel 216 + 217 + Optional properties when driving an eDP output: 218 + - nvidia,dpaux: phandle to a DispayPort AUX interface 219 + 220 + - dpaux: DisplayPort AUX interface 221 + - compatible: "nvidia,tegra124-dpaux" 222 + - reg: Physical base address and length of the controller's registers. 223 + - interrupts: The interrupt outputs from the controller. 224 + - clocks: Must contain an entry for each entry in clock-names. 225 + See ../clocks/clock-bindings.txt for details. 226 + - clock-names: Must include the following entries: 227 + - dpaux: clock input for the DPAUX hardware 228 + - parent: reference clock 229 + - resets: Must contain an entry for each entry in reset-names. 230 + See ../reset/reset.txt for details. 231 + - reset-names: Must include the following entries: 232 + - dpaux 233 + - vdd-supply: phandle of a supply that powers the DisplayPort link 234 + 193 235 Example: 194 236 195 237 / {
+2
drivers/gpu/drm/tegra/Makefile
··· 11 11 hdmi.o \ 12 12 mipi-phy.o \ 13 13 dsi.o \ 14 + sor.o \ 15 + dpaux.o \ 14 16 gr2d.o \ 15 17 gr3d.o 16 18
+1
drivers/gpu/drm/tegra/dc.h
··· 118 118 #define DC_DISP_DISP_WIN_OPTIONS 0x402 119 119 #define HDMI_ENABLE (1 << 30) 120 120 #define DSI_ENABLE (1 << 29) 121 + #define SOR_ENABLE (1 << 25) 121 122 122 123 #define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403 123 124 #define CURSOR_THRESHOLD(x) (((x) & 0x03) << 24)
+544
drivers/gpu/drm/tegra/dpaux.c
··· 1 + /* 2 + * Copyright (C) 2013 NVIDIA Corporation 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 7 + */ 8 + 9 + #include <linux/clk.h> 10 + #include <linux/delay.h> 11 + #include <linux/gpio.h> 12 + #include <linux/interrupt.h> 13 + #include <linux/io.h> 14 + #include <linux/of_gpio.h> 15 + #include <linux/platform_device.h> 16 + #include <linux/reset.h> 17 + #include <linux/regulator/consumer.h> 18 + 19 + #include <drm/drm_dp_helper.h> 20 + #include <drm/drm_panel.h> 21 + 22 + #include "dpaux.h" 23 + #include "drm.h" 24 + 25 + static DEFINE_MUTEX(dpaux_lock); 26 + static LIST_HEAD(dpaux_list); 27 + 28 + struct tegra_dpaux { 29 + struct drm_dp_aux aux; 30 + struct device *dev; 31 + 32 + void __iomem *regs; 33 + int irq; 34 + 35 + struct tegra_output *output; 36 + 37 + struct reset_control *rst; 38 + struct clk *clk_parent; 39 + struct clk *clk; 40 + 41 + struct regulator *vdd; 42 + 43 + struct completion complete; 44 + struct list_head list; 45 + }; 46 + 47 + static inline struct tegra_dpaux *to_dpaux(struct drm_dp_aux *aux) 48 + { 49 + return container_of(aux, struct tegra_dpaux, aux); 50 + } 51 + 52 + static inline unsigned long tegra_dpaux_readl(struct tegra_dpaux *dpaux, 53 + unsigned long offset) 54 + { 55 + return readl(dpaux->regs + (offset << 2)); 56 + } 57 + 58 + static inline void tegra_dpaux_writel(struct tegra_dpaux *dpaux, 59 + unsigned long value, 60 + unsigned long offset) 61 + { 62 + writel(value, dpaux->regs + (offset << 2)); 63 + } 64 + 65 + static void tegra_dpaux_write_fifo(struct tegra_dpaux *dpaux, const u8 *buffer, 66 + size_t size) 67 + { 68 + unsigned long offset = DPAUX_DP_AUXDATA_WRITE(0); 69 + size_t i, j; 70 + 71 + for (i = 0; i < size; i += 4) { 72 + size_t num = min_t(size_t, size - i, 4); 73 + unsigned long value = 0; 74 + 75 + for (j = 0; j < num; j++) 76 + value |= buffer[i + j] << (j * 8); 77 + 78 + tegra_dpaux_writel(dpaux, value, offset++); 79 + } 80 + } 81 + 82 + static void tegra_dpaux_read_fifo(struct tegra_dpaux *dpaux, u8 *buffer, 83 + size_t size) 84 + { 85 + unsigned long offset = DPAUX_DP_AUXDATA_READ(0); 86 + size_t i, j; 87 + 88 + for (i = 0; i < size; i += 4) { 89 + size_t num = min_t(size_t, size - i, 4); 90 + unsigned long value; 91 + 92 + value = tegra_dpaux_readl(dpaux, offset++); 93 + 94 + for (j = 0; j < num; j++) 95 + buffer[i + j] = value >> (j * 8); 96 + } 97 + } 98 + 99 + static ssize_t tegra_dpaux_transfer(struct drm_dp_aux *aux, 100 + struct drm_dp_aux_msg *msg) 101 + { 102 + unsigned long value = DPAUX_DP_AUXCTL_TRANSACTREQ; 103 + unsigned long timeout = msecs_to_jiffies(250); 104 + struct tegra_dpaux *dpaux = to_dpaux(aux); 105 + unsigned long status; 106 + ssize_t ret = 0; 107 + 108 + if (msg->size < 1 || msg->size > 16) 109 + return -EINVAL; 110 + 111 + tegra_dpaux_writel(dpaux, msg->address, DPAUX_DP_AUXADDR); 112 + 113 + switch (msg->request & ~DP_AUX_I2C_MOT) { 114 + case DP_AUX_I2C_WRITE: 115 + if (msg->request & DP_AUX_I2C_MOT) 116 + value = DPAUX_DP_AUXCTL_CMD_MOT_WR; 117 + else 118 + value = DPAUX_DP_AUXCTL_CMD_I2C_WR; 119 + 120 + break; 121 + 122 + case DP_AUX_I2C_READ: 123 + if (msg->request & DP_AUX_I2C_MOT) 124 + value = DPAUX_DP_AUXCTL_CMD_MOT_RD; 125 + else 126 + value = DPAUX_DP_AUXCTL_CMD_I2C_RD; 127 + 128 + break; 129 + 130 + case DP_AUX_I2C_STATUS: 131 + if (msg->request & DP_AUX_I2C_MOT) 132 + value = DPAUX_DP_AUXCTL_CMD_MOT_RQ; 133 + else 134 + value = DPAUX_DP_AUXCTL_CMD_I2C_RQ; 135 + 136 + break; 137 + 138 + case DP_AUX_NATIVE_WRITE: 139 + value = DPAUX_DP_AUXCTL_CMD_AUX_WR; 140 + break; 141 + 142 + case DP_AUX_NATIVE_READ: 143 + value = DPAUX_DP_AUXCTL_CMD_AUX_RD; 144 + break; 145 + 146 + default: 147 + return -EINVAL; 148 + } 149 + 150 + value |= DPAUX_DP_AUXCTL_CMDLEN(msg->size - 1); 151 + tegra_dpaux_writel(dpaux, value, DPAUX_DP_AUXCTL); 152 + 153 + if ((msg->request & DP_AUX_I2C_READ) == 0) { 154 + tegra_dpaux_write_fifo(dpaux, msg->buffer, msg->size); 155 + ret = msg->size; 156 + } 157 + 158 + /* start transaction */ 159 + value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXCTL); 160 + value |= DPAUX_DP_AUXCTL_TRANSACTREQ; 161 + tegra_dpaux_writel(dpaux, value, DPAUX_DP_AUXCTL); 162 + 163 + status = wait_for_completion_timeout(&dpaux->complete, timeout); 164 + if (!status) 165 + return -ETIMEDOUT; 166 + 167 + /* read status and clear errors */ 168 + value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXSTAT); 169 + tegra_dpaux_writel(dpaux, 0xf00, DPAUX_DP_AUXSTAT); 170 + 171 + if (value & DPAUX_DP_AUXSTAT_TIMEOUT_ERROR) 172 + return -ETIMEDOUT; 173 + 174 + if ((value & DPAUX_DP_AUXSTAT_RX_ERROR) || 175 + (value & DPAUX_DP_AUXSTAT_SINKSTAT_ERROR) || 176 + (value & DPAUX_DP_AUXSTAT_NO_STOP_ERROR)) 177 + return -EIO; 178 + 179 + switch ((value & DPAUX_DP_AUXSTAT_REPLY_TYPE_MASK) >> 16) { 180 + case 0x00: 181 + msg->reply = DP_AUX_NATIVE_REPLY_ACK; 182 + break; 183 + 184 + case 0x01: 185 + msg->reply = DP_AUX_NATIVE_REPLY_NACK; 186 + break; 187 + 188 + case 0x02: 189 + msg->reply = DP_AUX_NATIVE_REPLY_DEFER; 190 + break; 191 + 192 + case 0x04: 193 + msg->reply = DP_AUX_I2C_REPLY_NACK; 194 + break; 195 + 196 + case 0x08: 197 + msg->reply = DP_AUX_I2C_REPLY_DEFER; 198 + break; 199 + } 200 + 201 + if (msg->reply == DP_AUX_NATIVE_REPLY_ACK) { 202 + if (msg->request & DP_AUX_I2C_READ) { 203 + size_t count = value & DPAUX_DP_AUXSTAT_REPLY_MASK; 204 + 205 + if (WARN_ON(count != msg->size)) 206 + count = min_t(size_t, count, msg->size); 207 + 208 + tegra_dpaux_read_fifo(dpaux, msg->buffer, count); 209 + ret = count; 210 + } 211 + } 212 + 213 + return ret; 214 + } 215 + 216 + static irqreturn_t tegra_dpaux_irq(int irq, void *data) 217 + { 218 + struct tegra_dpaux *dpaux = data; 219 + irqreturn_t ret = IRQ_HANDLED; 220 + unsigned long value; 221 + 222 + /* clear interrupts */ 223 + value = tegra_dpaux_readl(dpaux, DPAUX_INTR_AUX); 224 + tegra_dpaux_writel(dpaux, value, DPAUX_INTR_AUX); 225 + 226 + if (value & DPAUX_INTR_PLUG_EVENT) { 227 + if (dpaux->output) { 228 + drm_helper_hpd_irq_event(dpaux->output->connector.dev); 229 + } 230 + } 231 + 232 + if (value & DPAUX_INTR_UNPLUG_EVENT) { 233 + if (dpaux->output) 234 + drm_helper_hpd_irq_event(dpaux->output->connector.dev); 235 + } 236 + 237 + if (value & DPAUX_INTR_IRQ_EVENT) { 238 + /* TODO: handle this */ 239 + } 240 + 241 + if (value & DPAUX_INTR_AUX_DONE) 242 + complete(&dpaux->complete); 243 + 244 + return ret; 245 + } 246 + 247 + static int tegra_dpaux_probe(struct platform_device *pdev) 248 + { 249 + struct tegra_dpaux *dpaux; 250 + struct resource *regs; 251 + unsigned long value; 252 + int err; 253 + 254 + dpaux = devm_kzalloc(&pdev->dev, sizeof(*dpaux), GFP_KERNEL); 255 + if (!dpaux) 256 + return -ENOMEM; 257 + 258 + init_completion(&dpaux->complete); 259 + INIT_LIST_HEAD(&dpaux->list); 260 + dpaux->dev = &pdev->dev; 261 + 262 + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 263 + dpaux->regs = devm_ioremap_resource(&pdev->dev, regs); 264 + if (IS_ERR(dpaux->regs)) 265 + return PTR_ERR(dpaux->regs); 266 + 267 + dpaux->irq = platform_get_irq(pdev, 0); 268 + if (dpaux->irq < 0) { 269 + dev_err(&pdev->dev, "failed to get IRQ\n"); 270 + return -ENXIO; 271 + } 272 + 273 + dpaux->rst = devm_reset_control_get(&pdev->dev, "dpaux"); 274 + if (IS_ERR(dpaux->rst)) 275 + return PTR_ERR(dpaux->rst); 276 + 277 + dpaux->clk = devm_clk_get(&pdev->dev, NULL); 278 + if (IS_ERR(dpaux->clk)) 279 + return PTR_ERR(dpaux->clk); 280 + 281 + err = clk_prepare_enable(dpaux->clk); 282 + if (err < 0) 283 + return err; 284 + 285 + reset_control_deassert(dpaux->rst); 286 + 287 + dpaux->clk_parent = devm_clk_get(&pdev->dev, "parent"); 288 + if (IS_ERR(dpaux->clk_parent)) 289 + return PTR_ERR(dpaux->clk_parent); 290 + 291 + err = clk_prepare_enable(dpaux->clk_parent); 292 + if (err < 0) 293 + return err; 294 + 295 + err = clk_set_rate(dpaux->clk_parent, 270000000); 296 + if (err < 0) { 297 + dev_err(&pdev->dev, "failed to set clock to 270 MHz: %d\n", 298 + err); 299 + return err; 300 + } 301 + 302 + dpaux->vdd = devm_regulator_get(&pdev->dev, "vdd"); 303 + if (IS_ERR(dpaux->vdd)) 304 + return PTR_ERR(dpaux->vdd); 305 + 306 + err = devm_request_irq(dpaux->dev, dpaux->irq, tegra_dpaux_irq, 0, 307 + dev_name(dpaux->dev), dpaux); 308 + if (err < 0) { 309 + dev_err(dpaux->dev, "failed to request IRQ#%u: %d\n", 310 + dpaux->irq, err); 311 + return err; 312 + } 313 + 314 + dpaux->aux.transfer = tegra_dpaux_transfer; 315 + dpaux->aux.dev = &pdev->dev; 316 + 317 + err = drm_dp_aux_register_i2c_bus(&dpaux->aux); 318 + if (err < 0) 319 + return err; 320 + 321 + /* enable and clear all interrupts */ 322 + value = DPAUX_INTR_AUX_DONE | DPAUX_INTR_IRQ_EVENT | 323 + DPAUX_INTR_UNPLUG_EVENT | DPAUX_INTR_PLUG_EVENT; 324 + tegra_dpaux_writel(dpaux, value, DPAUX_INTR_EN_AUX); 325 + tegra_dpaux_writel(dpaux, value, DPAUX_INTR_AUX); 326 + 327 + mutex_lock(&dpaux_lock); 328 + list_add_tail(&dpaux->list, &dpaux_list); 329 + mutex_unlock(&dpaux_lock); 330 + 331 + platform_set_drvdata(pdev, dpaux); 332 + 333 + return 0; 334 + } 335 + 336 + static int tegra_dpaux_remove(struct platform_device *pdev) 337 + { 338 + struct tegra_dpaux *dpaux = platform_get_drvdata(pdev); 339 + 340 + drm_dp_aux_unregister_i2c_bus(&dpaux->aux); 341 + 342 + mutex_lock(&dpaux_lock); 343 + list_del(&dpaux->list); 344 + mutex_unlock(&dpaux_lock); 345 + 346 + clk_disable_unprepare(dpaux->clk_parent); 347 + reset_control_assert(dpaux->rst); 348 + clk_disable_unprepare(dpaux->clk); 349 + 350 + return 0; 351 + } 352 + 353 + static const struct of_device_id tegra_dpaux_of_match[] = { 354 + { .compatible = "nvidia,tegra124-dpaux", }, 355 + { }, 356 + }; 357 + 358 + struct platform_driver tegra_dpaux_driver = { 359 + .driver = { 360 + .name = "tegra-dpaux", 361 + .of_match_table = tegra_dpaux_of_match, 362 + }, 363 + .probe = tegra_dpaux_probe, 364 + .remove = tegra_dpaux_remove, 365 + }; 366 + 367 + struct tegra_dpaux *tegra_dpaux_find_by_of_node(struct device_node *np) 368 + { 369 + struct tegra_dpaux *dpaux; 370 + 371 + mutex_lock(&dpaux_lock); 372 + 373 + list_for_each_entry(dpaux, &dpaux_list, list) 374 + if (np == dpaux->dev->of_node) { 375 + mutex_unlock(&dpaux_lock); 376 + return dpaux; 377 + } 378 + 379 + mutex_unlock(&dpaux_lock); 380 + 381 + return NULL; 382 + } 383 + 384 + int tegra_dpaux_attach(struct tegra_dpaux *dpaux, struct tegra_output *output) 385 + { 386 + unsigned long timeout; 387 + int err; 388 + 389 + dpaux->output = output; 390 + 391 + err = regulator_enable(dpaux->vdd); 392 + if (err < 0) 393 + return err; 394 + 395 + timeout = jiffies + msecs_to_jiffies(250); 396 + 397 + while (time_before(jiffies, timeout)) { 398 + enum drm_connector_status status; 399 + 400 + status = tegra_dpaux_detect(dpaux); 401 + if (status == connector_status_connected) 402 + return 0; 403 + 404 + usleep_range(1000, 2000); 405 + } 406 + 407 + return -ETIMEDOUT; 408 + } 409 + 410 + int tegra_dpaux_detach(struct tegra_dpaux *dpaux) 411 + { 412 + unsigned long timeout; 413 + int err; 414 + 415 + err = regulator_disable(dpaux->vdd); 416 + if (err < 0) 417 + return err; 418 + 419 + timeout = jiffies + msecs_to_jiffies(250); 420 + 421 + while (time_before(jiffies, timeout)) { 422 + enum drm_connector_status status; 423 + 424 + status = tegra_dpaux_detect(dpaux); 425 + if (status == connector_status_disconnected) { 426 + dpaux->output = NULL; 427 + return 0; 428 + } 429 + 430 + usleep_range(1000, 2000); 431 + } 432 + 433 + return -ETIMEDOUT; 434 + } 435 + 436 + enum drm_connector_status tegra_dpaux_detect(struct tegra_dpaux *dpaux) 437 + { 438 + unsigned long value; 439 + 440 + value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXSTAT); 441 + 442 + if (value & DPAUX_DP_AUXSTAT_HPD_STATUS) 443 + return connector_status_connected; 444 + 445 + return connector_status_disconnected; 446 + } 447 + 448 + int tegra_dpaux_enable(struct tegra_dpaux *dpaux) 449 + { 450 + unsigned long value; 451 + 452 + value = DPAUX_HYBRID_PADCTL_AUX_CMH(2) | 453 + DPAUX_HYBRID_PADCTL_AUX_DRVZ(4) | 454 + DPAUX_HYBRID_PADCTL_AUX_DRVI(0x18) | 455 + DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV | 456 + DPAUX_HYBRID_PADCTL_MODE_AUX; 457 + tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_PADCTL); 458 + 459 + value = tegra_dpaux_readl(dpaux, DPAUX_HYBRID_SPARE); 460 + value &= ~DPAUX_HYBRID_SPARE_PAD_POWER_DOWN; 461 + tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_SPARE); 462 + 463 + return 0; 464 + } 465 + 466 + int tegra_dpaux_disable(struct tegra_dpaux *dpaux) 467 + { 468 + unsigned long value; 469 + 470 + value = tegra_dpaux_readl(dpaux, DPAUX_HYBRID_SPARE); 471 + value |= DPAUX_HYBRID_SPARE_PAD_POWER_DOWN; 472 + tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_SPARE); 473 + 474 + return 0; 475 + } 476 + 477 + int tegra_dpaux_prepare(struct tegra_dpaux *dpaux, u8 encoding) 478 + { 479 + int err; 480 + 481 + err = drm_dp_dpcd_writeb(&dpaux->aux, DP_MAIN_LINK_CHANNEL_CODING_SET, 482 + encoding); 483 + if (err < 0) 484 + return err; 485 + 486 + return 0; 487 + } 488 + 489 + int tegra_dpaux_train(struct tegra_dpaux *dpaux, struct drm_dp_link *link, 490 + u8 pattern) 491 + { 492 + u8 tp = pattern & DP_TRAINING_PATTERN_MASK; 493 + u8 status[DP_LINK_STATUS_SIZE], values[4]; 494 + unsigned int i; 495 + int err; 496 + 497 + err = drm_dp_dpcd_writeb(&dpaux->aux, DP_TRAINING_PATTERN_SET, pattern); 498 + if (err < 0) 499 + return err; 500 + 501 + if (tp == DP_TRAINING_PATTERN_DISABLE) 502 + return 0; 503 + 504 + for (i = 0; i < link->num_lanes; i++) 505 + values[i] = DP_TRAIN_MAX_PRE_EMPHASIS_REACHED | 506 + DP_TRAIN_PRE_EMPHASIS_0 | 507 + DP_TRAIN_MAX_SWING_REACHED | 508 + DP_TRAIN_VOLTAGE_SWING_400; 509 + 510 + err = drm_dp_dpcd_write(&dpaux->aux, DP_TRAINING_LANE0_SET, values, 511 + link->num_lanes); 512 + if (err < 0) 513 + return err; 514 + 515 + usleep_range(500, 1000); 516 + 517 + err = drm_dp_dpcd_read_link_status(&dpaux->aux, status); 518 + if (err < 0) 519 + return err; 520 + 521 + switch (tp) { 522 + case DP_TRAINING_PATTERN_1: 523 + if (!drm_dp_clock_recovery_ok(status, link->num_lanes)) 524 + return -EAGAIN; 525 + 526 + break; 527 + 528 + case DP_TRAINING_PATTERN_2: 529 + if (!drm_dp_channel_eq_ok(status, link->num_lanes)) 530 + return -EAGAIN; 531 + 532 + break; 533 + 534 + default: 535 + dev_err(dpaux->dev, "unsupported training pattern %u\n", tp); 536 + return -EINVAL; 537 + } 538 + 539 + err = drm_dp_dpcd_writeb(&dpaux->aux, DP_EDP_CONFIGURATION_SET, 0); 540 + if (err < 0) 541 + return err; 542 + 543 + return 0; 544 + }
+73
drivers/gpu/drm/tegra/dpaux.h
··· 1 + /* 2 + * Copyright (C) 2013 NVIDIA Corporation 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 7 + */ 8 + 9 + #ifndef DRM_TEGRA_DPAUX_H 10 + #define DRM_TEGRA_DPAUX_H 11 + 12 + #define DPAUX_CTXSW 0x00 13 + 14 + #define DPAUX_INTR_EN_AUX 0x01 15 + #define DPAUX_INTR_AUX 0x05 16 + #define DPAUX_INTR_AUX_DONE (1 << 3) 17 + #define DPAUX_INTR_IRQ_EVENT (1 << 2) 18 + #define DPAUX_INTR_UNPLUG_EVENT (1 << 1) 19 + #define DPAUX_INTR_PLUG_EVENT (1 << 0) 20 + 21 + #define DPAUX_DP_AUXDATA_WRITE(x) (0x09 + ((x) << 2)) 22 + #define DPAUX_DP_AUXDATA_READ(x) (0x19 + ((x) << 2)) 23 + #define DPAUX_DP_AUXADDR 0x29 24 + 25 + #define DPAUX_DP_AUXCTL 0x2d 26 + #define DPAUX_DP_AUXCTL_TRANSACTREQ (1 << 16) 27 + #define DPAUX_DP_AUXCTL_CMD_AUX_RD (9 << 12) 28 + #define DPAUX_DP_AUXCTL_CMD_AUX_WR (8 << 12) 29 + #define DPAUX_DP_AUXCTL_CMD_MOT_RQ (6 << 12) 30 + #define DPAUX_DP_AUXCTL_CMD_MOT_RD (5 << 12) 31 + #define DPAUX_DP_AUXCTL_CMD_MOT_WR (4 << 12) 32 + #define DPAUX_DP_AUXCTL_CMD_I2C_RQ (2 << 12) 33 + #define DPAUX_DP_AUXCTL_CMD_I2C_RD (1 << 12) 34 + #define DPAUX_DP_AUXCTL_CMD_I2C_WR (0 << 12) 35 + #define DPAUX_DP_AUXCTL_CMDLEN(x) ((x) & 0xff) 36 + 37 + #define DPAUX_DP_AUXSTAT 0x31 38 + #define DPAUX_DP_AUXSTAT_HPD_STATUS (1 << 28) 39 + #define DPAUX_DP_AUXSTAT_REPLY_TYPE_MASK (0xf0000) 40 + #define DPAUX_DP_AUXSTAT_NO_STOP_ERROR (1 << 11) 41 + #define DPAUX_DP_AUXSTAT_SINKSTAT_ERROR (1 << 10) 42 + #define DPAUX_DP_AUXSTAT_RX_ERROR (1 << 9) 43 + #define DPAUX_DP_AUXSTAT_TIMEOUT_ERROR (1 << 8) 44 + #define DPAUX_DP_AUXSTAT_REPLY_MASK (0xff) 45 + 46 + #define DPAUX_DP_AUX_SINKSTAT_LO 0x35 47 + #define DPAUX_DP_AUX_SINKSTAT_HI 0x39 48 + 49 + #define DPAUX_HPD_CONFIG 0x3d 50 + #define DPAUX_HPD_CONFIG_UNPLUG_MIN_TIME(x) (((x) & 0xffff) << 16) 51 + #define DPAUX_HPD_CONFIG_PLUG_MIN_TIME(x) ((x) & 0xffff) 52 + 53 + #define DPAUX_HPD_IRQ_CONFIG 0x41 54 + #define DPAUX_HPD_IRQ_CONFIG_MIN_LOW_TIME(x) ((x) & 0xffff) 55 + 56 + #define DPAUX_DP_AUX_CONFIG 0x45 57 + 58 + #define DPAUX_HYBRID_PADCTL 0x49 59 + #define DPAUX_HYBRID_PADCTL_AUX_CMH(x) (((x) & 0x3) << 12) 60 + #define DPAUX_HYBRID_PADCTL_AUX_DRVZ(x) (((x) & 0x7) << 8) 61 + #define DPAUX_HYBRID_PADCTL_AUX_DRVI(x) (((x) & 0x3f) << 2) 62 + #define DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV (1 << 1) 63 + #define DPAUX_HYBRID_PADCTL_MODE_I2C (1 << 0) 64 + #define DPAUX_HYBRID_PADCTL_MODE_AUX (0 << 0) 65 + 66 + #define DPAUX_HYBRID_SPARE 0x4d 67 + #define DPAUX_HYBRID_SPARE_PAD_POWER_DOWN (1 << 0) 68 + 69 + #define DPAUX_SCRATCH_REG0 0x51 70 + #define DPAUX_SCRATCH_REG1 0x55 71 + #define DPAUX_SCRATCH_REG2 0x59 72 + 73 + #endif
+17 -2
drivers/gpu/drm/tegra/drm.c
··· 665 665 { .compatible = "nvidia,tegra114-hdmi", }, 666 666 { .compatible = "nvidia,tegra114-gr3d", }, 667 667 { .compatible = "nvidia,tegra124-dc", }, 668 + { .compatible = "nvidia,tegra124-sor", }, 668 669 { /* sentinel */ } 669 670 }; 670 671 ··· 692 691 if (err < 0) 693 692 goto unregister_dc; 694 693 695 - err = platform_driver_register(&tegra_hdmi_driver); 694 + err = platform_driver_register(&tegra_sor_driver); 696 695 if (err < 0) 697 696 goto unregister_dsi; 698 697 699 - err = platform_driver_register(&tegra_gr2d_driver); 698 + err = platform_driver_register(&tegra_hdmi_driver); 699 + if (err < 0) 700 + goto unregister_sor; 701 + 702 + err = platform_driver_register(&tegra_dpaux_driver); 700 703 if (err < 0) 701 704 goto unregister_hdmi; 705 + 706 + err = platform_driver_register(&tegra_gr2d_driver); 707 + if (err < 0) 708 + goto unregister_dpaux; 702 709 703 710 err = platform_driver_register(&tegra_gr3d_driver); 704 711 if (err < 0) ··· 716 707 717 708 unregister_gr2d: 718 709 platform_driver_unregister(&tegra_gr2d_driver); 710 + unregister_dpaux: 711 + platform_driver_unregister(&tegra_dpaux_driver); 719 712 unregister_hdmi: 720 713 platform_driver_unregister(&tegra_hdmi_driver); 714 + unregister_sor: 715 + platform_driver_unregister(&tegra_sor_driver); 721 716 unregister_dsi: 722 717 platform_driver_unregister(&tegra_dsi_driver); 723 718 unregister_dc: ··· 736 723 { 737 724 platform_driver_unregister(&tegra_gr3d_driver); 738 725 platform_driver_unregister(&tegra_gr2d_driver); 726 + platform_driver_unregister(&tegra_dpaux_driver); 739 727 platform_driver_unregister(&tegra_hdmi_driver); 728 + platform_driver_unregister(&tegra_sor_driver); 740 729 platform_driver_unregister(&tegra_dsi_driver); 741 730 platform_driver_unregister(&tegra_dc_driver); 742 731 host1x_driver_unregister(&host1x_drm_driver);
+20
drivers/gpu/drm/tegra/drm.h
··· 179 179 int (*check_mode)(struct tegra_output *output, 180 180 struct drm_display_mode *mode, 181 181 enum drm_mode_status *status); 182 + enum drm_connector_status (*detect)(struct tegra_output *output); 182 183 }; 183 184 184 185 enum tegra_output_type { 185 186 TEGRA_OUTPUT_RGB, 186 187 TEGRA_OUTPUT_HDMI, 187 188 TEGRA_OUTPUT_DSI, 189 + TEGRA_OUTPUT_EDP, 188 190 }; 189 191 190 192 struct tegra_output { ··· 267 265 extern int tegra_output_init(struct drm_device *drm, struct tegra_output *output); 268 266 extern int tegra_output_exit(struct tegra_output *output); 269 267 268 + /* from dpaux.c */ 269 + 270 + struct tegra_dpaux; 271 + struct drm_dp_link; 272 + struct drm_dp_aux; 273 + 274 + struct tegra_dpaux *tegra_dpaux_find_by_of_node(struct device_node *np); 275 + enum drm_connector_status tegra_dpaux_detect(struct tegra_dpaux *dpaux); 276 + int tegra_dpaux_attach(struct tegra_dpaux *dpaux, struct tegra_output *output); 277 + int tegra_dpaux_detach(struct tegra_dpaux *dpaux); 278 + int tegra_dpaux_enable(struct tegra_dpaux *dpaux); 279 + int tegra_dpaux_disable(struct tegra_dpaux *dpaux); 280 + int tegra_dpaux_prepare(struct tegra_dpaux *dpaux, u8 encoding); 281 + int tegra_dpaux_train(struct tegra_dpaux *dpaux, struct drm_dp_link *link, 282 + u8 pattern); 283 + 270 284 /* from fb.c */ 271 285 struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer, 272 286 unsigned int index); ··· 296 278 297 279 extern struct platform_driver tegra_dc_driver; 298 280 extern struct platform_driver tegra_dsi_driver; 281 + extern struct platform_driver tegra_sor_driver; 299 282 extern struct platform_driver tegra_hdmi_driver; 283 + extern struct platform_driver tegra_dpaux_driver; 300 284 extern struct platform_driver tegra_gr2d_driver; 301 285 extern struct platform_driver tegra_gr3d_driver; 302 286
+3 -17
drivers/gpu/drm/tegra/dsi.c
··· 1 1 /* 2 2 * Copyright (C) 2013 NVIDIA Corporation 3 3 * 4 - * Permission to use, copy, modify, distribute, and sell this software and its 5 - * documentation for any purpose is hereby granted without fee, provided that 6 - * the above copyright notice appear in all copies and that both that copyright 7 - * notice and this permission notice appear in supporting documentation, and 8 - * that the name of the copyright holders not be used in advertising or 9 - * publicity pertaining to distribution of the software without specific, 10 - * written prior permission. The copyright holders make no representations 11 - * about the suitability of this software for any purpose. It is provided "as 12 - * is" without express or implied warranty. 13 - * 14 - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20 - * OF THIS SOFTWARE. 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 21 7 */ 22 8 23 9 #include <linux/clk.h>
+3 -17
drivers/gpu/drm/tegra/dsi.h
··· 1 1 /* 2 2 * Copyright (C) 2013 NVIDIA Corporation 3 3 * 4 - * Permission to use, copy, modify, distribute, and sell this software and its 5 - * documentation for any purpose is hereby granted without fee, provided that 6 - * the above copyright notice appear in all copies and that both that copyright 7 - * notice and this permission notice appear in supporting documentation, and 8 - * that the name of the copyright holders not be used in advertising or 9 - * publicity pertaining to distribution of the software without specific, 10 - * written prior permission. The copyright holders make no representations 11 - * about the suitability of this software for any purpose. It is provided "as 12 - * is" without express or implied warranty. 13 - * 14 - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20 - * OF THIS SOFTWARE. 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 21 7 */ 22 8 23 9 #ifndef DRM_TEGRA_DSI_H
+17 -8
drivers/gpu/drm/tegra/gem.c
··· 8 8 * 9 9 * Copyright (c) 2011 Samsung Electronics Co., Ltd. 10 10 * 11 - * This program is free software; you can redistribute it and/or 12 - * modify it under the terms of the GNU General Public License 13 - * as published by the Free Software Foundation; either version 2 14 - * of the License, or (at your option) any later version. 15 - * This program is distributed in the hope that it will be useful, 16 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 - * GNU General Public License for more details. 11 + * This program is free software; you can redistribute it and/or modify 12 + * it under the terms of the GNU General Public License version 2 as 13 + * published by the Free Software Foundation. 19 14 */ 20 15 21 16 #include <linux/dma-buf.h> ··· 389 394 return -EINVAL; 390 395 } 391 396 397 + static void *tegra_gem_prime_vmap(struct dma_buf *buf) 398 + { 399 + struct drm_gem_object *gem = buf->priv; 400 + struct tegra_bo *bo = to_tegra_bo(gem); 401 + 402 + return bo->vaddr; 403 + } 404 + 405 + static void tegra_gem_prime_vunmap(struct dma_buf *buf, void *vaddr) 406 + { 407 + } 408 + 392 409 static const struct dma_buf_ops tegra_gem_prime_dmabuf_ops = { 393 410 .map_dma_buf = tegra_gem_prime_map_dma_buf, 394 411 .unmap_dma_buf = tegra_gem_prime_unmap_dma_buf, ··· 410 403 .kmap = tegra_gem_prime_kmap, 411 404 .kunmap = tegra_gem_prime_kunmap, 412 405 .mmap = tegra_gem_prime_mmap, 406 + .vmap = tegra_gem_prime_vmap, 407 + .vunmap = tegra_gem_prime_vunmap, 413 408 }; 414 409 415 410 struct dma_buf *tegra_gem_prime_export(struct drm_device *drm,
+3 -11
drivers/gpu/drm/tegra/gem.h
··· 3 3 * 4 4 * Copyright (c) 2012-2013, NVIDIA Corporation. 5 5 * 6 - * This program is free software; you can redistribute it and/or modify it 7 - * under the terms and conditions of the GNU General Public License, 8 - * version 2, as published by the Free Software Foundation. 9 - * 10 - * This program is distributed in the hope it will be useful, but WITHOUT 11 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 - * more details. 14 - * 15 - * You should have received a copy of the GNU General Public License 16 - * along with this program. If not, see <http://www.gnu.org/licenses/>. 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 as 8 + * published by the Free Software Foundation. 17 9 */ 18 10 19 11 #ifndef __HOST1X_GEM_H
+3 -11
drivers/gpu/drm/tegra/gr2d.c
··· 1 1 /* 2 2 * Copyright (c) 2012-2013, NVIDIA Corporation. 3 3 * 4 - * This program is free software; you can redistribute it and/or modify it 5 - * under the terms and conditions of the GNU General Public License, 6 - * version 2, as published by the Free Software Foundation. 7 - * 8 - * This program is distributed in the hope it will be useful, but WITHOUT 9 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 - * more details. 12 - * 13 - * You should have received a copy of the GNU General Public License 14 - * along with this program. If not, see <http://www.gnu.org/licenses/>. 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 15 7 */ 16 8 17 9 #include <linux/clk.h>
+3 -17
drivers/gpu/drm/tegra/mipi-phy.c
··· 1 1 /* 2 2 * Copyright (C) 2013 NVIDIA Corporation 3 3 * 4 - * Permission to use, copy, modify, distribute, and sell this software and its 5 - * documentation for any purpose is hereby granted without fee, provided that 6 - * the above copyright notice appear in all copies and that both that copyright 7 - * notice and this permission notice appear in supporting documentation, and 8 - * that the name of the copyright holders not be used in advertising or 9 - * publicity pertaining to distribution of the software without specific, 10 - * written prior permission. The copyright holders make no representations 11 - * about the suitability of this software for any purpose. It is provided "as 12 - * is" without express or implied warranty. 13 - * 14 - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20 - * OF THIS SOFTWARE. 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 21 7 */ 22 8 23 9 #include <linux/errno.h>
+3 -17
drivers/gpu/drm/tegra/mipi-phy.h
··· 1 1 /* 2 2 * Copyright (C) 2013 NVIDIA Corporation 3 3 * 4 - * Permission to use, copy, modify, distribute, and sell this software and its 5 - * documentation for any purpose is hereby granted without fee, provided that 6 - * the above copyright notice appear in all copies and that both that copyright 7 - * notice and this permission notice appear in supporting documentation, and 8 - * that the name of the copyright holders not be used in advertising or 9 - * publicity pertaining to distribution of the software without specific, 10 - * written prior permission. The copyright holders make no representations 11 - * about the suitability of this software for any purpose. It is provided "as 12 - * is" without express or implied warranty. 13 - * 14 - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20 - * OF THIS SOFTWARE. 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 21 7 */ 22 8 23 9 #ifndef DRM_TEGRA_MIPI_PHY_H
+8
drivers/gpu/drm/tegra/output.c
··· 77 77 struct tegra_output *output = connector_to_output(connector); 78 78 enum drm_connector_status status = connector_status_unknown; 79 79 80 + if (output->ops->detect) 81 + return output->ops->detect(output); 82 + 80 83 if (gpio_is_valid(output->hpd_gpio)) { 81 84 if (gpio_get_value(output->hpd_gpio) == 0) 82 85 status = connector_status_disconnected; ··· 293 290 case TEGRA_OUTPUT_DSI: 294 291 connector = DRM_MODE_CONNECTOR_DSI; 295 292 encoder = DRM_MODE_ENCODER_DSI; 293 + break; 294 + 295 + case TEGRA_OUTPUT_EDP: 296 + connector = DRM_MODE_CONNECTOR_eDP; 297 + encoder = DRM_MODE_ENCODER_TMDS; 296 298 break; 297 299 298 300 default:
+1092
drivers/gpu/drm/tegra/sor.c
··· 1 + /* 2 + * Copyright (C) 2013 NVIDIA Corporation 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 7 + */ 8 + 9 + #include <linux/clk.h> 10 + #include <linux/io.h> 11 + #include <linux/platform_device.h> 12 + #include <linux/reset.h> 13 + #include <linux/tegra-powergate.h> 14 + 15 + #include <drm/drm_dp_helper.h> 16 + 17 + #include "dc.h" 18 + #include "drm.h" 19 + #include "sor.h" 20 + 21 + struct tegra_sor { 22 + struct host1x_client client; 23 + struct tegra_output output; 24 + struct device *dev; 25 + 26 + void __iomem *regs; 27 + 28 + struct reset_control *rst; 29 + struct clk *clk_parent; 30 + struct clk *clk_safe; 31 + struct clk *clk_dp; 32 + struct clk *clk; 33 + 34 + struct tegra_dpaux *dpaux; 35 + 36 + bool enabled; 37 + }; 38 + 39 + static inline struct tegra_sor * 40 + host1x_client_to_sor(struct host1x_client *client) 41 + { 42 + return container_of(client, struct tegra_sor, client); 43 + } 44 + 45 + static inline struct tegra_sor *to_sor(struct tegra_output *output) 46 + { 47 + return container_of(output, struct tegra_sor, output); 48 + } 49 + 50 + static inline unsigned long tegra_sor_readl(struct tegra_sor *sor, 51 + unsigned long offset) 52 + { 53 + return readl(sor->regs + (offset << 2)); 54 + } 55 + 56 + static inline void tegra_sor_writel(struct tegra_sor *sor, unsigned long value, 57 + unsigned long offset) 58 + { 59 + writel(value, sor->regs + (offset << 2)); 60 + } 61 + 62 + static int tegra_sor_dp_train_fast(struct tegra_sor *sor, 63 + struct drm_dp_link *link) 64 + { 65 + unsigned long value; 66 + unsigned int i; 67 + u8 pattern; 68 + int err; 69 + 70 + /* setup lane parameters */ 71 + value = SOR_LANE_DRIVE_CURRENT_LANE3(0x40) | 72 + SOR_LANE_DRIVE_CURRENT_LANE2(0x40) | 73 + SOR_LANE_DRIVE_CURRENT_LANE1(0x40) | 74 + SOR_LANE_DRIVE_CURRENT_LANE0(0x40); 75 + tegra_sor_writel(sor, value, SOR_LANE_DRIVE_CURRENT_0); 76 + 77 + value = SOR_LANE_PREEMPHASIS_LANE3(0x0f) | 78 + SOR_LANE_PREEMPHASIS_LANE2(0x0f) | 79 + SOR_LANE_PREEMPHASIS_LANE1(0x0f) | 80 + SOR_LANE_PREEMPHASIS_LANE0(0x0f); 81 + tegra_sor_writel(sor, value, SOR_LANE_PREEMPHASIS_0); 82 + 83 + value = SOR_LANE_POST_CURSOR_LANE3(0x00) | 84 + SOR_LANE_POST_CURSOR_LANE2(0x00) | 85 + SOR_LANE_POST_CURSOR_LANE1(0x00) | 86 + SOR_LANE_POST_CURSOR_LANE0(0x00); 87 + tegra_sor_writel(sor, value, SOR_LANE_POST_CURSOR_0); 88 + 89 + /* disable LVDS mode */ 90 + tegra_sor_writel(sor, 0, SOR_LVDS); 91 + 92 + value = tegra_sor_readl(sor, SOR_DP_PADCTL_0); 93 + value |= SOR_DP_PADCTL_TX_PU_ENABLE; 94 + value &= ~SOR_DP_PADCTL_TX_PU_MASK; 95 + value |= SOR_DP_PADCTL_TX_PU(2); /* XXX: don't hardcode? */ 96 + tegra_sor_writel(sor, value, SOR_DP_PADCTL_0); 97 + 98 + value = tegra_sor_readl(sor, SOR_DP_PADCTL_0); 99 + value |= SOR_DP_PADCTL_CM_TXD_3 | SOR_DP_PADCTL_CM_TXD_2 | 100 + SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0; 101 + tegra_sor_writel(sor, value, SOR_DP_PADCTL_0); 102 + 103 + usleep_range(10, 100); 104 + 105 + value = tegra_sor_readl(sor, SOR_DP_PADCTL_0); 106 + value &= ~(SOR_DP_PADCTL_CM_TXD_3 | SOR_DP_PADCTL_CM_TXD_2 | 107 + SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0); 108 + tegra_sor_writel(sor, value, SOR_DP_PADCTL_0); 109 + 110 + err = tegra_dpaux_prepare(sor->dpaux, DP_SET_ANSI_8B10B); 111 + if (err < 0) 112 + return err; 113 + 114 + for (i = 0, value = 0; i < link->num_lanes; i++) { 115 + unsigned long lane = SOR_DP_TPG_CHANNEL_CODING | 116 + SOR_DP_TPG_SCRAMBLER_NONE | 117 + SOR_DP_TPG_PATTERN_TRAIN1; 118 + value = (value << 8) | lane; 119 + } 120 + 121 + tegra_sor_writel(sor, value, SOR_DP_TPG); 122 + 123 + pattern = DP_TRAINING_PATTERN_1; 124 + 125 + err = tegra_dpaux_train(sor->dpaux, link, pattern); 126 + if (err < 0) 127 + return err; 128 + 129 + value = tegra_sor_readl(sor, SOR_DP_SPARE_0); 130 + value |= SOR_DP_SPARE_SEQ_ENABLE; 131 + value &= ~SOR_DP_SPARE_PANEL_INTERNAL; 132 + value |= SOR_DP_SPARE_MACRO_SOR_CLK; 133 + tegra_sor_writel(sor, value, SOR_DP_SPARE_0); 134 + 135 + for (i = 0, value = 0; i < link->num_lanes; i++) { 136 + unsigned long lane = SOR_DP_TPG_CHANNEL_CODING | 137 + SOR_DP_TPG_SCRAMBLER_NONE | 138 + SOR_DP_TPG_PATTERN_TRAIN2; 139 + value = (value << 8) | lane; 140 + } 141 + 142 + tegra_sor_writel(sor, value, SOR_DP_TPG); 143 + 144 + pattern = DP_LINK_SCRAMBLING_DISABLE | DP_TRAINING_PATTERN_2; 145 + 146 + err = tegra_dpaux_train(sor->dpaux, link, pattern); 147 + if (err < 0) 148 + return err; 149 + 150 + for (i = 0, value = 0; i < link->num_lanes; i++) { 151 + unsigned long lane = SOR_DP_TPG_CHANNEL_CODING | 152 + SOR_DP_TPG_SCRAMBLER_GALIOS | 153 + SOR_DP_TPG_PATTERN_NONE; 154 + value = (value << 8) | lane; 155 + } 156 + 157 + tegra_sor_writel(sor, value, SOR_DP_TPG); 158 + 159 + pattern = DP_TRAINING_PATTERN_DISABLE; 160 + 161 + err = tegra_dpaux_train(sor->dpaux, link, pattern); 162 + if (err < 0) 163 + return err; 164 + 165 + return 0; 166 + } 167 + 168 + static void tegra_sor_super_update(struct tegra_sor *sor) 169 + { 170 + tegra_sor_writel(sor, 0, SOR_SUPER_STATE_0); 171 + tegra_sor_writel(sor, 1, SOR_SUPER_STATE_0); 172 + tegra_sor_writel(sor, 0, SOR_SUPER_STATE_0); 173 + } 174 + 175 + static void tegra_sor_update(struct tegra_sor *sor) 176 + { 177 + tegra_sor_writel(sor, 0, SOR_STATE_0); 178 + tegra_sor_writel(sor, 1, SOR_STATE_0); 179 + tegra_sor_writel(sor, 0, SOR_STATE_0); 180 + } 181 + 182 + static int tegra_sor_setup_pwm(struct tegra_sor *sor, unsigned long timeout) 183 + { 184 + unsigned long value; 185 + 186 + value = tegra_sor_readl(sor, SOR_PWM_DIV); 187 + value &= ~SOR_PWM_DIV_MASK; 188 + value |= 0x400; /* period */ 189 + tegra_sor_writel(sor, value, SOR_PWM_DIV); 190 + 191 + value = tegra_sor_readl(sor, SOR_PWM_CTL); 192 + value &= ~SOR_PWM_CTL_DUTY_CYCLE_MASK; 193 + value |= 0x400; /* duty cycle */ 194 + value &= ~SOR_PWM_CTL_CLK_SEL; /* clock source: PCLK */ 195 + value |= SOR_PWM_CTL_TRIGGER; 196 + tegra_sor_writel(sor, value, SOR_PWM_CTL); 197 + 198 + timeout = jiffies + msecs_to_jiffies(timeout); 199 + 200 + while (time_before(jiffies, timeout)) { 201 + value = tegra_sor_readl(sor, SOR_PWM_CTL); 202 + if ((value & SOR_PWM_CTL_TRIGGER) == 0) 203 + return 0; 204 + 205 + usleep_range(25, 100); 206 + } 207 + 208 + return -ETIMEDOUT; 209 + } 210 + 211 + static int tegra_sor_attach(struct tegra_sor *sor) 212 + { 213 + unsigned long value, timeout; 214 + 215 + /* wake up in normal mode */ 216 + value = tegra_sor_readl(sor, SOR_SUPER_STATE_1); 217 + value |= SOR_SUPER_STATE_HEAD_MODE_AWAKE; 218 + value |= SOR_SUPER_STATE_MODE_NORMAL; 219 + tegra_sor_writel(sor, value, SOR_SUPER_STATE_1); 220 + tegra_sor_super_update(sor); 221 + 222 + /* attach */ 223 + value = tegra_sor_readl(sor, SOR_SUPER_STATE_1); 224 + value |= SOR_SUPER_STATE_ATTACHED; 225 + tegra_sor_writel(sor, value, SOR_SUPER_STATE_1); 226 + tegra_sor_super_update(sor); 227 + 228 + timeout = jiffies + msecs_to_jiffies(250); 229 + 230 + while (time_before(jiffies, timeout)) { 231 + value = tegra_sor_readl(sor, SOR_TEST); 232 + if ((value & SOR_TEST_ATTACHED) != 0) 233 + return 0; 234 + 235 + usleep_range(25, 100); 236 + } 237 + 238 + return -ETIMEDOUT; 239 + } 240 + 241 + static int tegra_sor_wakeup(struct tegra_sor *sor) 242 + { 243 + struct tegra_dc *dc = to_tegra_dc(sor->output.encoder.crtc); 244 + unsigned long value, timeout; 245 + 246 + /* enable display controller outputs */ 247 + value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL); 248 + value |= PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | 249 + PW4_ENABLE | PM0_ENABLE | PM1_ENABLE; 250 + tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL); 251 + 252 + tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL); 253 + tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); 254 + 255 + timeout = jiffies + msecs_to_jiffies(250); 256 + 257 + /* wait for head to wake up */ 258 + while (time_before(jiffies, timeout)) { 259 + value = tegra_sor_readl(sor, SOR_TEST); 260 + value &= SOR_TEST_HEAD_MODE_MASK; 261 + 262 + if (value == SOR_TEST_HEAD_MODE_AWAKE) 263 + return 0; 264 + 265 + usleep_range(25, 100); 266 + } 267 + 268 + return -ETIMEDOUT; 269 + } 270 + 271 + static int tegra_sor_power_up(struct tegra_sor *sor, unsigned long timeout) 272 + { 273 + unsigned long value; 274 + 275 + value = tegra_sor_readl(sor, SOR_PWR); 276 + value |= SOR_PWR_TRIGGER | SOR_PWR_NORMAL_STATE_PU; 277 + tegra_sor_writel(sor, value, SOR_PWR); 278 + 279 + timeout = jiffies + msecs_to_jiffies(timeout); 280 + 281 + while (time_before(jiffies, timeout)) { 282 + value = tegra_sor_readl(sor, SOR_PWR); 283 + if ((value & SOR_PWR_TRIGGER) == 0) 284 + return 0; 285 + 286 + usleep_range(25, 100); 287 + } 288 + 289 + return -ETIMEDOUT; 290 + } 291 + 292 + static int tegra_output_sor_enable(struct tegra_output *output) 293 + { 294 + struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc); 295 + struct drm_display_mode *mode = &dc->base.mode; 296 + unsigned int vbe, vse, hbe, hse, vbs, hbs, i; 297 + struct tegra_sor *sor = to_sor(output); 298 + unsigned long value; 299 + int err; 300 + 301 + if (sor->enabled) 302 + return 0; 303 + 304 + err = clk_prepare_enable(sor->clk); 305 + if (err < 0) 306 + return err; 307 + 308 + reset_control_deassert(sor->rst); 309 + 310 + if (sor->dpaux) { 311 + err = tegra_dpaux_enable(sor->dpaux); 312 + if (err < 0) 313 + dev_err(sor->dev, "failed to enable DP: %d\n", err); 314 + } 315 + 316 + err = clk_set_parent(sor->clk, sor->clk_safe); 317 + if (err < 0) 318 + dev_err(sor->dev, "failed to set safe parent clock: %d\n", err); 319 + 320 + value = tegra_sor_readl(sor, SOR_CLK_CNTRL); 321 + value &= ~SOR_CLK_CNTRL_DP_CLK_SEL_MASK; 322 + value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK; 323 + tegra_sor_writel(sor, value, SOR_CLK_CNTRL); 324 + 325 + value = tegra_sor_readl(sor, SOR_PLL_2); 326 + value &= ~SOR_PLL_2_BANDGAP_POWERDOWN; 327 + tegra_sor_writel(sor, value, SOR_PLL_2); 328 + usleep_range(20, 100); 329 + 330 + value = tegra_sor_readl(sor, SOR_PLL_3); 331 + value |= SOR_PLL_3_PLL_VDD_MODE_V3_3; 332 + tegra_sor_writel(sor, value, SOR_PLL_3); 333 + 334 + value = SOR_PLL_0_ICHPMP(0xf) | SOR_PLL_0_VCOCAP_RST | 335 + SOR_PLL_0_PLLREG_LEVEL_V45 | SOR_PLL_0_RESISTOR_EXT; 336 + tegra_sor_writel(sor, value, SOR_PLL_0); 337 + 338 + value = tegra_sor_readl(sor, SOR_PLL_2); 339 + value |= SOR_PLL_2_SEQ_PLLCAPPD; 340 + value &= ~SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE; 341 + value |= SOR_PLL_2_LVDS_ENABLE; 342 + tegra_sor_writel(sor, value, SOR_PLL_2); 343 + 344 + value = SOR_PLL_1_TERM_COMPOUT | SOR_PLL_1_TMDS_TERM; 345 + tegra_sor_writel(sor, value, SOR_PLL_1); 346 + 347 + while (true) { 348 + value = tegra_sor_readl(sor, SOR_PLL_2); 349 + if ((value & SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE) == 0) 350 + break; 351 + 352 + usleep_range(250, 1000); 353 + } 354 + 355 + value = tegra_sor_readl(sor, SOR_PLL_2); 356 + value &= ~SOR_PLL_2_POWERDOWN_OVERRIDE; 357 + value &= ~SOR_PLL_2_PORT_POWERDOWN; 358 + tegra_sor_writel(sor, value, SOR_PLL_2); 359 + 360 + /* 361 + * power up 362 + */ 363 + 364 + /* set safe link bandwidth (1.62 Gbps) */ 365 + value = tegra_sor_readl(sor, SOR_CLK_CNTRL); 366 + value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK; 367 + value |= SOR_CLK_CNTRL_DP_LINK_SPEED_G1_62; 368 + tegra_sor_writel(sor, value, SOR_CLK_CNTRL); 369 + 370 + /* step 1 */ 371 + value = tegra_sor_readl(sor, SOR_PLL_2); 372 + value |= SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE | SOR_PLL_2_PORT_POWERDOWN | 373 + SOR_PLL_2_BANDGAP_POWERDOWN; 374 + tegra_sor_writel(sor, value, SOR_PLL_2); 375 + 376 + value = tegra_sor_readl(sor, SOR_PLL_0); 377 + value |= SOR_PLL_0_VCOPD | SOR_PLL_0_POWER_OFF; 378 + tegra_sor_writel(sor, value, SOR_PLL_0); 379 + 380 + value = tegra_sor_readl(sor, SOR_DP_PADCTL_0); 381 + value &= ~SOR_DP_PADCTL_PAD_CAL_PD; 382 + tegra_sor_writel(sor, value, SOR_DP_PADCTL_0); 383 + 384 + /* step 2 */ 385 + err = tegra_io_rail_power_on(TEGRA_IO_RAIL_LVDS); 386 + if (err < 0) { 387 + dev_err(sor->dev, "failed to power on I/O rail: %d\n", err); 388 + return err; 389 + } 390 + 391 + usleep_range(5, 100); 392 + 393 + /* step 3 */ 394 + value = tegra_sor_readl(sor, SOR_PLL_2); 395 + value &= ~SOR_PLL_2_BANDGAP_POWERDOWN; 396 + tegra_sor_writel(sor, value, SOR_PLL_2); 397 + 398 + usleep_range(20, 100); 399 + 400 + /* step 4 */ 401 + value = tegra_sor_readl(sor, SOR_PLL_0); 402 + value &= ~SOR_PLL_0_POWER_OFF; 403 + value &= ~SOR_PLL_0_VCOPD; 404 + tegra_sor_writel(sor, value, SOR_PLL_0); 405 + 406 + value = tegra_sor_readl(sor, SOR_PLL_2); 407 + value &= ~SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE; 408 + tegra_sor_writel(sor, value, SOR_PLL_2); 409 + 410 + usleep_range(200, 1000); 411 + 412 + /* step 5 */ 413 + value = tegra_sor_readl(sor, SOR_PLL_2); 414 + value &= ~SOR_PLL_2_PORT_POWERDOWN; 415 + tegra_sor_writel(sor, value, SOR_PLL_2); 416 + 417 + /* switch to DP clock */ 418 + err = clk_set_parent(sor->clk, sor->clk_dp); 419 + if (err < 0) 420 + dev_err(sor->dev, "failed to set DP parent clock: %d\n", err); 421 + 422 + /* power dplanes (XXX parameterize based on link?) */ 423 + value = tegra_sor_readl(sor, SOR_DP_PADCTL_0); 424 + value |= SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_0 | 425 + SOR_DP_PADCTL_PD_TXD_1 | SOR_DP_PADCTL_PD_TXD_2; 426 + tegra_sor_writel(sor, value, SOR_DP_PADCTL_0); 427 + 428 + value = tegra_sor_readl(sor, SOR_DP_LINKCTL_0); 429 + value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK; 430 + value |= SOR_DP_LINKCTL_LANE_COUNT(4); 431 + tegra_sor_writel(sor, value, SOR_DP_LINKCTL_0); 432 + 433 + /* start lane sequencer */ 434 + value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_DOWN | 435 + SOR_LANE_SEQ_CTL_POWER_STATE_UP; 436 + tegra_sor_writel(sor, value, SOR_LANE_SEQ_CTL); 437 + 438 + while (true) { 439 + value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL); 440 + if ((value & SOR_LANE_SEQ_CTL_TRIGGER) == 0) 441 + break; 442 + 443 + usleep_range(250, 1000); 444 + } 445 + 446 + /* set link bandwidth (2.7 GHz, XXX: parameterize based on link?) */ 447 + value = tegra_sor_readl(sor, SOR_CLK_CNTRL); 448 + value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK; 449 + value |= SOR_CLK_CNTRL_DP_LINK_SPEED_G2_70; 450 + tegra_sor_writel(sor, value, SOR_CLK_CNTRL); 451 + 452 + /* set linkctl */ 453 + value = tegra_sor_readl(sor, SOR_DP_LINKCTL_0); 454 + value |= SOR_DP_LINKCTL_ENABLE; 455 + 456 + value &= ~SOR_DP_LINKCTL_TU_SIZE_MASK; 457 + value |= SOR_DP_LINKCTL_TU_SIZE(59); /* XXX: don't hardcode? */ 458 + 459 + value |= SOR_DP_LINKCTL_ENHANCED_FRAME; 460 + tegra_sor_writel(sor, value, SOR_DP_LINKCTL_0); 461 + 462 + for (i = 0, value = 0; i < 4; i++) { 463 + unsigned long lane = SOR_DP_TPG_CHANNEL_CODING | 464 + SOR_DP_TPG_SCRAMBLER_GALIOS | 465 + SOR_DP_TPG_PATTERN_NONE; 466 + value = (value << 8) | lane; 467 + } 468 + 469 + tegra_sor_writel(sor, value, SOR_DP_TPG); 470 + 471 + value = tegra_sor_readl(sor, SOR_DP_CONFIG_0); 472 + value &= ~SOR_DP_CONFIG_WATERMARK_MASK; 473 + value |= SOR_DP_CONFIG_WATERMARK(14); /* XXX: don't hardcode? */ 474 + 475 + value &= ~SOR_DP_CONFIG_ACTIVE_SYM_COUNT_MASK; 476 + value |= SOR_DP_CONFIG_ACTIVE_SYM_COUNT(47); /* XXX: don't hardcode? */ 477 + 478 + value &= ~SOR_DP_CONFIG_ACTIVE_SYM_FRAC_MASK; 479 + value |= SOR_DP_CONFIG_ACTIVE_SYM_FRAC(9); /* XXX: don't hardcode? */ 480 + 481 + value &= ~SOR_DP_CONFIG_ACTIVE_SYM_POLARITY; /* XXX: don't hardcode? */ 482 + 483 + value |= SOR_DP_CONFIG_ACTIVE_SYM_ENABLE; 484 + value |= SOR_DP_CONFIG_DISPARITY_NEGATIVE; /* XXX: don't hardcode? */ 485 + tegra_sor_writel(sor, value, SOR_DP_CONFIG_0); 486 + 487 + value = tegra_sor_readl(sor, SOR_DP_AUDIO_HBLANK_SYMBOLS); 488 + value &= ~SOR_DP_AUDIO_HBLANK_SYMBOLS_MASK; 489 + value |= 137; /* XXX: don't hardcode? */ 490 + tegra_sor_writel(sor, value, SOR_DP_AUDIO_HBLANK_SYMBOLS); 491 + 492 + value = tegra_sor_readl(sor, SOR_DP_AUDIO_VBLANK_SYMBOLS); 493 + value &= ~SOR_DP_AUDIO_VBLANK_SYMBOLS_MASK; 494 + value |= 2368; /* XXX: don't hardcode? */ 495 + tegra_sor_writel(sor, value, SOR_DP_AUDIO_VBLANK_SYMBOLS); 496 + 497 + /* enable pad calibration logic */ 498 + value = tegra_sor_readl(sor, SOR_DP_PADCTL_0); 499 + value |= SOR_DP_PADCTL_PAD_CAL_PD; 500 + tegra_sor_writel(sor, value, SOR_DP_PADCTL_0); 501 + 502 + if (sor->dpaux) { 503 + /* FIXME: properly convert to struct drm_dp_aux */ 504 + struct drm_dp_aux *aux = (struct drm_dp_aux *)sor->dpaux; 505 + struct drm_dp_link link; 506 + u8 rate, lanes; 507 + 508 + err = drm_dp_link_probe(aux, &link); 509 + if (err < 0) { 510 + dev_err(sor->dev, "failed to probe eDP link: %d\n", 511 + err); 512 + return err; 513 + } 514 + 515 + err = drm_dp_link_power_up(aux, &link); 516 + if (err < 0) { 517 + dev_err(sor->dev, "failed to power up eDP link: %d\n", 518 + err); 519 + return err; 520 + } 521 + 522 + err = drm_dp_link_configure(aux, &link); 523 + if (err < 0) { 524 + dev_err(sor->dev, "failed to configure eDP link: %d\n", 525 + err); 526 + return err; 527 + } 528 + 529 + rate = drm_dp_link_rate_to_bw_code(link.rate); 530 + lanes = link.num_lanes; 531 + 532 + value = tegra_sor_readl(sor, SOR_CLK_CNTRL); 533 + value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK; 534 + value |= SOR_CLK_CNTRL_DP_LINK_SPEED(rate); 535 + tegra_sor_writel(sor, value, SOR_CLK_CNTRL); 536 + 537 + value = tegra_sor_readl(sor, SOR_DP_LINKCTL_0); 538 + value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK; 539 + value |= SOR_DP_LINKCTL_LANE_COUNT(lanes); 540 + 541 + if (link.capabilities & DP_LINK_CAP_ENHANCED_FRAMING) 542 + value |= SOR_DP_LINKCTL_ENHANCED_FRAME; 543 + 544 + tegra_sor_writel(sor, value, SOR_DP_LINKCTL_0); 545 + 546 + /* disable training pattern generator */ 547 + 548 + for (i = 0; i < link.num_lanes; i++) { 549 + unsigned long lane = SOR_DP_TPG_CHANNEL_CODING | 550 + SOR_DP_TPG_SCRAMBLER_GALIOS | 551 + SOR_DP_TPG_PATTERN_NONE; 552 + value = (value << 8) | lane; 553 + } 554 + 555 + tegra_sor_writel(sor, value, SOR_DP_TPG); 556 + 557 + err = tegra_sor_dp_train_fast(sor, &link); 558 + if (err < 0) { 559 + dev_err(sor->dev, "DP fast link training failed: %d\n", 560 + err); 561 + return err; 562 + } 563 + 564 + dev_dbg(sor->dev, "fast link training succeeded\n"); 565 + } 566 + 567 + err = tegra_sor_power_up(sor, 250); 568 + if (err < 0) { 569 + dev_err(sor->dev, "failed to power up SOR: %d\n", err); 570 + return err; 571 + } 572 + 573 + /* start display controller in continuous mode */ 574 + value = tegra_dc_readl(dc, DC_CMD_STATE_ACCESS); 575 + value |= WRITE_MUX; 576 + tegra_dc_writel(dc, value, DC_CMD_STATE_ACCESS); 577 + 578 + tegra_dc_writel(dc, VSYNC_H_POSITION(1), DC_DISP_DISP_TIMING_OPTIONS); 579 + tegra_dc_writel(dc, DISP_CTRL_MODE_C_DISPLAY, DC_CMD_DISPLAY_COMMAND); 580 + 581 + value = tegra_dc_readl(dc, DC_CMD_STATE_ACCESS); 582 + value &= ~WRITE_MUX; 583 + tegra_dc_writel(dc, value, DC_CMD_STATE_ACCESS); 584 + 585 + /* 586 + * configure panel (24bpp, vsync-, hsync-, DP-A protocol, complete 587 + * raster, associate with display controller) 588 + */ 589 + value = SOR_STATE_ASY_PIXELDEPTH_BPP_24_444 | 590 + SOR_STATE_ASY_VSYNCPOL | 591 + SOR_STATE_ASY_HSYNCPOL | 592 + SOR_STATE_ASY_PROTOCOL_DP_A | 593 + SOR_STATE_ASY_CRC_MODE_COMPLETE | 594 + SOR_STATE_ASY_OWNER(dc->pipe + 1); 595 + tegra_sor_writel(sor, value, SOR_STATE_1); 596 + 597 + /* 598 + * TODO: The video timing programming below doesn't seem to match the 599 + * register definitions. 600 + */ 601 + 602 + value = ((mode->vtotal & 0x7fff) << 16) | (mode->htotal & 0x7fff); 603 + tegra_sor_writel(sor, value, SOR_HEAD_STATE_1(0)); 604 + 605 + vse = mode->vsync_end - mode->vsync_start - 1; 606 + hse = mode->hsync_end - mode->hsync_start - 1; 607 + 608 + value = ((vse & 0x7fff) << 16) | (hse & 0x7fff); 609 + tegra_sor_writel(sor, value, SOR_HEAD_STATE_2(0)); 610 + 611 + vbe = vse + (mode->vsync_start - mode->vdisplay); 612 + hbe = hse + (mode->hsync_start - mode->hdisplay); 613 + 614 + value = ((vbe & 0x7fff) << 16) | (hbe & 0x7fff); 615 + tegra_sor_writel(sor, value, SOR_HEAD_STATE_3(0)); 616 + 617 + vbs = vbe + mode->vdisplay; 618 + hbs = hbe + mode->hdisplay; 619 + 620 + value = ((vbs & 0x7fff) << 16) | (hbs & 0x7fff); 621 + tegra_sor_writel(sor, value, SOR_HEAD_STATE_4(0)); 622 + 623 + /* XXX interlaced mode */ 624 + tegra_sor_writel(sor, 0x00000001, SOR_HEAD_STATE_5(0)); 625 + 626 + /* CSTM (LVDS, link A/B, upper) */ 627 + value = SOR_CSTM_LVDS | SOR_CSTM_LINK_ACT_B | SOR_CSTM_LINK_ACT_B | 628 + SOR_CSTM_UPPER; 629 + tegra_sor_writel(sor, value, SOR_CSTM); 630 + 631 + /* PWM setup */ 632 + err = tegra_sor_setup_pwm(sor, 250); 633 + if (err < 0) { 634 + dev_err(sor->dev, "failed to setup PWM: %d\n", err); 635 + return err; 636 + } 637 + 638 + value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); 639 + value |= SOR_ENABLE; 640 + tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); 641 + 642 + tegra_sor_update(sor); 643 + 644 + err = tegra_sor_attach(sor); 645 + if (err < 0) { 646 + dev_err(sor->dev, "failed to attach SOR: %d\n", err); 647 + return err; 648 + } 649 + 650 + err = tegra_sor_wakeup(sor); 651 + if (err < 0) { 652 + dev_err(sor->dev, "failed to enable DC: %d\n", err); 653 + return err; 654 + } 655 + 656 + sor->enabled = true; 657 + 658 + return 0; 659 + } 660 + 661 + static int tegra_sor_detach(struct tegra_sor *sor) 662 + { 663 + unsigned long value, timeout; 664 + 665 + /* switch to safe mode */ 666 + value = tegra_sor_readl(sor, SOR_SUPER_STATE_1); 667 + value &= ~SOR_SUPER_STATE_MODE_NORMAL; 668 + tegra_sor_writel(sor, value, SOR_SUPER_STATE_1); 669 + tegra_sor_super_update(sor); 670 + 671 + timeout = jiffies + msecs_to_jiffies(250); 672 + 673 + while (time_before(jiffies, timeout)) { 674 + value = tegra_sor_readl(sor, SOR_PWR); 675 + if (value & SOR_PWR_MODE_SAFE) 676 + break; 677 + } 678 + 679 + if ((value & SOR_PWR_MODE_SAFE) == 0) 680 + return -ETIMEDOUT; 681 + 682 + /* go to sleep */ 683 + value = tegra_sor_readl(sor, SOR_SUPER_STATE_1); 684 + value &= ~SOR_SUPER_STATE_HEAD_MODE_MASK; 685 + tegra_sor_writel(sor, value, SOR_SUPER_STATE_1); 686 + tegra_sor_super_update(sor); 687 + 688 + /* detach */ 689 + value = tegra_sor_readl(sor, SOR_SUPER_STATE_1); 690 + value &= ~SOR_SUPER_STATE_ATTACHED; 691 + tegra_sor_writel(sor, value, SOR_SUPER_STATE_1); 692 + tegra_sor_super_update(sor); 693 + 694 + timeout = jiffies + msecs_to_jiffies(250); 695 + 696 + while (time_before(jiffies, timeout)) { 697 + value = tegra_sor_readl(sor, SOR_TEST); 698 + if ((value & SOR_TEST_ATTACHED) == 0) 699 + break; 700 + 701 + usleep_range(25, 100); 702 + } 703 + 704 + if ((value & SOR_TEST_ATTACHED) != 0) 705 + return -ETIMEDOUT; 706 + 707 + return 0; 708 + } 709 + 710 + static int tegra_sor_power_down(struct tegra_sor *sor) 711 + { 712 + unsigned long value, timeout; 713 + int err; 714 + 715 + value = tegra_sor_readl(sor, SOR_PWR); 716 + value &= ~SOR_PWR_NORMAL_STATE_PU; 717 + value |= SOR_PWR_TRIGGER; 718 + tegra_sor_writel(sor, value, SOR_PWR); 719 + 720 + timeout = jiffies + msecs_to_jiffies(250); 721 + 722 + while (time_before(jiffies, timeout)) { 723 + value = tegra_sor_readl(sor, SOR_PWR); 724 + if ((value & SOR_PWR_TRIGGER) == 0) 725 + return 0; 726 + 727 + usleep_range(25, 100); 728 + } 729 + 730 + if ((value & SOR_PWR_TRIGGER) != 0) 731 + return -ETIMEDOUT; 732 + 733 + err = clk_set_parent(sor->clk, sor->clk_safe); 734 + if (err < 0) 735 + dev_err(sor->dev, "failed to set safe parent clock: %d\n", err); 736 + 737 + value = tegra_sor_readl(sor, SOR_DP_PADCTL_0); 738 + value &= ~(SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_0 | 739 + SOR_DP_PADCTL_PD_TXD_1 | SOR_DP_PADCTL_PD_TXD_2); 740 + tegra_sor_writel(sor, value, SOR_DP_PADCTL_0); 741 + 742 + /* stop lane sequencer */ 743 + value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_DOWN | 744 + SOR_LANE_SEQ_CTL_POWER_STATE_DOWN; 745 + tegra_sor_writel(sor, value, SOR_LANE_SEQ_CTL); 746 + 747 + timeout = jiffies + msecs_to_jiffies(250); 748 + 749 + while (time_before(jiffies, timeout)) { 750 + value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL); 751 + if ((value & SOR_LANE_SEQ_CTL_TRIGGER) == 0) 752 + break; 753 + 754 + usleep_range(25, 100); 755 + } 756 + 757 + if ((value & SOR_LANE_SEQ_CTL_TRIGGER) != 0) 758 + return -ETIMEDOUT; 759 + 760 + value = tegra_sor_readl(sor, SOR_PLL_2); 761 + value |= SOR_PLL_2_PORT_POWERDOWN; 762 + tegra_sor_writel(sor, value, SOR_PLL_2); 763 + 764 + usleep_range(20, 100); 765 + 766 + value = tegra_sor_readl(sor, SOR_PLL_0); 767 + value |= SOR_PLL_0_POWER_OFF; 768 + value |= SOR_PLL_0_VCOPD; 769 + tegra_sor_writel(sor, value, SOR_PLL_0); 770 + 771 + value = tegra_sor_readl(sor, SOR_PLL_2); 772 + value |= SOR_PLL_2_SEQ_PLLCAPPD; 773 + value |= SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE; 774 + tegra_sor_writel(sor, value, SOR_PLL_2); 775 + 776 + usleep_range(20, 100); 777 + 778 + return 0; 779 + } 780 + 781 + static int tegra_output_sor_disable(struct tegra_output *output) 782 + { 783 + struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc); 784 + struct tegra_sor *sor = to_sor(output); 785 + unsigned long value; 786 + int err; 787 + 788 + if (!sor->enabled) 789 + return 0; 790 + 791 + err = tegra_sor_detach(sor); 792 + if (err < 0) { 793 + dev_err(sor->dev, "failed to detach SOR: %d\n", err); 794 + return err; 795 + } 796 + 797 + tegra_sor_writel(sor, 0, SOR_STATE_1); 798 + tegra_sor_update(sor); 799 + 800 + /* 801 + * The following accesses registers of the display controller, so make 802 + * sure it's only executed when the output is attached to one. 803 + */ 804 + if (dc) { 805 + /* 806 + * XXX: We can't do this here because it causes the SOR to go 807 + * into an erroneous state and the output will look scrambled 808 + * the next time it is enabled. Presumably this is because we 809 + * should be doing this only on the next VBLANK. A possible 810 + * solution would be to queue a "power-off" event to trigger 811 + * this code to be run during the next VBLANK. 812 + */ 813 + /* 814 + value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL); 815 + value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | 816 + PW4_ENABLE | PM0_ENABLE | PM1_ENABLE); 817 + tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL); 818 + */ 819 + 820 + value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND); 821 + value &= ~DISP_CTRL_MODE_MASK; 822 + tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND); 823 + 824 + value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); 825 + value &= ~SOR_ENABLE; 826 + tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); 827 + 828 + tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL); 829 + tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); 830 + } 831 + 832 + err = tegra_sor_power_down(sor); 833 + if (err < 0) { 834 + dev_err(sor->dev, "failed to power down SOR: %d\n", err); 835 + return err; 836 + } 837 + 838 + if (sor->dpaux) { 839 + err = tegra_dpaux_disable(sor->dpaux); 840 + if (err < 0) { 841 + dev_err(sor->dev, "failed to disable DP: %d\n", err); 842 + return err; 843 + } 844 + } 845 + 846 + err = tegra_io_rail_power_off(TEGRA_IO_RAIL_LVDS); 847 + if (err < 0) { 848 + dev_err(sor->dev, "failed to power off I/O rail: %d\n", err); 849 + return err; 850 + } 851 + 852 + reset_control_assert(sor->rst); 853 + clk_disable_unprepare(sor->clk); 854 + 855 + sor->enabled = false; 856 + 857 + return 0; 858 + } 859 + 860 + static int tegra_output_sor_setup_clock(struct tegra_output *output, 861 + struct clk *clk, unsigned long pclk) 862 + { 863 + struct tegra_sor *sor = to_sor(output); 864 + int err; 865 + 866 + /* round to next MHz */ 867 + pclk = DIV_ROUND_UP(pclk / 2, 1000000) * 1000000; 868 + 869 + err = clk_set_parent(clk, sor->clk_parent); 870 + if (err < 0) { 871 + dev_err(sor->dev, "failed to set parent clock: %d\n", err); 872 + return err; 873 + } 874 + 875 + err = clk_set_rate(sor->clk_parent, pclk); 876 + if (err < 0) { 877 + dev_err(sor->dev, "failed to set base clock rate to %lu Hz\n", 878 + pclk * 2); 879 + return err; 880 + } 881 + 882 + return 0; 883 + } 884 + 885 + static int tegra_output_sor_check_mode(struct tegra_output *output, 886 + struct drm_display_mode *mode, 887 + enum drm_mode_status *status) 888 + { 889 + /* 890 + * FIXME: For now, always assume that the mode is okay. 891 + */ 892 + 893 + *status = MODE_OK; 894 + 895 + return 0; 896 + } 897 + 898 + static enum drm_connector_status 899 + tegra_output_sor_detect(struct tegra_output *output) 900 + { 901 + struct tegra_sor *sor = to_sor(output); 902 + 903 + if (sor->dpaux) 904 + return tegra_dpaux_detect(sor->dpaux); 905 + 906 + return connector_status_unknown; 907 + } 908 + 909 + static const struct tegra_output_ops sor_ops = { 910 + .enable = tegra_output_sor_enable, 911 + .disable = tegra_output_sor_disable, 912 + .setup_clock = tegra_output_sor_setup_clock, 913 + .check_mode = tegra_output_sor_check_mode, 914 + .detect = tegra_output_sor_detect, 915 + }; 916 + 917 + static int tegra_sor_init(struct host1x_client *client) 918 + { 919 + struct tegra_drm *tegra = dev_get_drvdata(client->parent); 920 + struct tegra_sor *sor = host1x_client_to_sor(client); 921 + int err; 922 + 923 + if (!sor->dpaux) 924 + return -ENODEV; 925 + 926 + sor->output.type = TEGRA_OUTPUT_EDP; 927 + 928 + sor->output.dev = sor->dev; 929 + sor->output.ops = &sor_ops; 930 + 931 + err = tegra_output_init(tegra->drm, &sor->output); 932 + if (err < 0) { 933 + dev_err(sor->dev, "output setup failed: %d\n", err); 934 + return err; 935 + } 936 + 937 + if (sor->dpaux) { 938 + err = tegra_dpaux_attach(sor->dpaux, &sor->output); 939 + if (err < 0) { 940 + dev_err(sor->dev, "failed to attach DP: %d\n", err); 941 + return err; 942 + } 943 + } 944 + 945 + return 0; 946 + } 947 + 948 + static int tegra_sor_exit(struct host1x_client *client) 949 + { 950 + struct tegra_sor *sor = host1x_client_to_sor(client); 951 + int err; 952 + 953 + err = tegra_output_disable(&sor->output); 954 + if (err < 0) { 955 + dev_err(sor->dev, "output failed to disable: %d\n", err); 956 + return err; 957 + } 958 + 959 + if (sor->dpaux) { 960 + err = tegra_dpaux_detach(sor->dpaux); 961 + if (err < 0) { 962 + dev_err(sor->dev, "failed to detach DP: %d\n", err); 963 + return err; 964 + } 965 + } 966 + 967 + err = tegra_output_exit(&sor->output); 968 + if (err < 0) { 969 + dev_err(sor->dev, "output cleanup failed: %d\n", err); 970 + return err; 971 + } 972 + 973 + return 0; 974 + } 975 + 976 + static const struct host1x_client_ops sor_client_ops = { 977 + .init = tegra_sor_init, 978 + .exit = tegra_sor_exit, 979 + }; 980 + 981 + static int tegra_sor_probe(struct platform_device *pdev) 982 + { 983 + struct device_node *np; 984 + struct tegra_sor *sor; 985 + struct resource *regs; 986 + int err; 987 + 988 + sor = devm_kzalloc(&pdev->dev, sizeof(*sor), GFP_KERNEL); 989 + if (!sor) 990 + return -ENOMEM; 991 + 992 + sor->output.dev = sor->dev = &pdev->dev; 993 + 994 + np = of_parse_phandle(pdev->dev.of_node, "nvidia,dpaux", 0); 995 + if (np) { 996 + sor->dpaux = tegra_dpaux_find_by_of_node(np); 997 + of_node_put(np); 998 + 999 + if (!sor->dpaux) 1000 + return -EPROBE_DEFER; 1001 + } 1002 + 1003 + err = tegra_output_probe(&sor->output); 1004 + if (err < 0) 1005 + return err; 1006 + 1007 + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1008 + sor->regs = devm_ioremap_resource(&pdev->dev, regs); 1009 + if (IS_ERR(sor->regs)) 1010 + return PTR_ERR(sor->regs); 1011 + 1012 + sor->rst = devm_reset_control_get(&pdev->dev, "sor"); 1013 + if (IS_ERR(sor->rst)) 1014 + return PTR_ERR(sor->rst); 1015 + 1016 + sor->clk = devm_clk_get(&pdev->dev, NULL); 1017 + if (IS_ERR(sor->clk)) 1018 + return PTR_ERR(sor->clk); 1019 + 1020 + sor->clk_parent = devm_clk_get(&pdev->dev, "parent"); 1021 + if (IS_ERR(sor->clk_parent)) 1022 + return PTR_ERR(sor->clk_parent); 1023 + 1024 + err = clk_prepare_enable(sor->clk_parent); 1025 + if (err < 0) 1026 + return err; 1027 + 1028 + sor->clk_safe = devm_clk_get(&pdev->dev, "safe"); 1029 + if (IS_ERR(sor->clk_safe)) 1030 + return PTR_ERR(sor->clk_safe); 1031 + 1032 + err = clk_prepare_enable(sor->clk_safe); 1033 + if (err < 0) 1034 + return err; 1035 + 1036 + sor->clk_dp = devm_clk_get(&pdev->dev, "dp"); 1037 + if (IS_ERR(sor->clk_dp)) 1038 + return PTR_ERR(sor->clk_dp); 1039 + 1040 + err = clk_prepare_enable(sor->clk_dp); 1041 + if (err < 0) 1042 + return err; 1043 + 1044 + INIT_LIST_HEAD(&sor->client.list); 1045 + sor->client.ops = &sor_client_ops; 1046 + sor->client.dev = &pdev->dev; 1047 + 1048 + err = host1x_client_register(&sor->client); 1049 + if (err < 0) { 1050 + dev_err(&pdev->dev, "failed to register host1x client: %d\n", 1051 + err); 1052 + return err; 1053 + } 1054 + 1055 + platform_set_drvdata(pdev, sor); 1056 + 1057 + return 0; 1058 + } 1059 + 1060 + static int tegra_sor_remove(struct platform_device *pdev) 1061 + { 1062 + struct tegra_sor *sor = platform_get_drvdata(pdev); 1063 + int err; 1064 + 1065 + err = host1x_client_unregister(&sor->client); 1066 + if (err < 0) { 1067 + dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", 1068 + err); 1069 + return err; 1070 + } 1071 + 1072 + clk_disable_unprepare(sor->clk_parent); 1073 + clk_disable_unprepare(sor->clk_safe); 1074 + clk_disable_unprepare(sor->clk_dp); 1075 + clk_disable_unprepare(sor->clk); 1076 + 1077 + return 0; 1078 + } 1079 + 1080 + static const struct of_device_id tegra_sor_of_match[] = { 1081 + { .compatible = "nvidia,tegra124-sor", }, 1082 + { }, 1083 + }; 1084 + 1085 + struct platform_driver tegra_sor_driver = { 1086 + .driver = { 1087 + .name = "tegra-sor", 1088 + .of_match_table = tegra_sor_of_match, 1089 + }, 1090 + .probe = tegra_sor_probe, 1091 + .remove = tegra_sor_remove, 1092 + };
+278
drivers/gpu/drm/tegra/sor.h
··· 1 + /* 2 + * Copyright (C) 2013 NVIDIA Corporation 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 7 + */ 8 + 9 + #ifndef DRM_TEGRA_SOR_H 10 + #define DRM_TEGRA_SOR_H 11 + 12 + #define SOR_CTXSW 0x00 13 + 14 + #define SOR_SUPER_STATE_0 0x01 15 + 16 + #define SOR_SUPER_STATE_1 0x02 17 + #define SOR_SUPER_STATE_ATTACHED (1 << 3) 18 + #define SOR_SUPER_STATE_MODE_NORMAL (1 << 2) 19 + #define SOR_SUPER_STATE_HEAD_MODE_MASK (3 << 0) 20 + #define SOR_SUPER_STATE_HEAD_MODE_AWAKE (2 << 0) 21 + #define SOR_SUPER_STATE_HEAD_MODE_SNOOZE (1 << 0) 22 + #define SOR_SUPER_STATE_HEAD_MODE_SLEEP (0 << 0) 23 + 24 + #define SOR_STATE_0 0x03 25 + 26 + #define SOR_STATE_1 0x04 27 + #define SOR_STATE_ASY_PIXELDEPTH_MASK (0xf << 17) 28 + #define SOR_STATE_ASY_PIXELDEPTH_BPP_18_444 (0x2 << 17) 29 + #define SOR_STATE_ASY_PIXELDEPTH_BPP_24_444 (0x5 << 17) 30 + #define SOR_STATE_ASY_VSYNCPOL (1 << 13) 31 + #define SOR_STATE_ASY_HSYNCPOL (1 << 12) 32 + #define SOR_STATE_ASY_PROTOCOL_MASK (0xf << 8) 33 + #define SOR_STATE_ASY_PROTOCOL_CUSTOM (0xf << 8) 34 + #define SOR_STATE_ASY_PROTOCOL_DP_A (0x8 << 8) 35 + #define SOR_STATE_ASY_PROTOCOL_DP_B (0x9 << 8) 36 + #define SOR_STATE_ASY_PROTOCOL_LVDS (0x0 << 8) 37 + #define SOR_STATE_ASY_CRC_MODE_MASK (0x3 << 6) 38 + #define SOR_STATE_ASY_CRC_MODE_NON_ACTIVE (0x2 << 6) 39 + #define SOR_STATE_ASY_CRC_MODE_COMPLETE (0x1 << 6) 40 + #define SOR_STATE_ASY_CRC_MODE_ACTIVE (0x0 << 6) 41 + #define SOR_STATE_ASY_OWNER(x) (((x) & 0xf) << 0) 42 + 43 + #define SOR_HEAD_STATE_0(x) (0x05 + (x)) 44 + #define SOR_HEAD_STATE_1(x) (0x07 + (x)) 45 + #define SOR_HEAD_STATE_2(x) (0x09 + (x)) 46 + #define SOR_HEAD_STATE_3(x) (0x0b + (x)) 47 + #define SOR_HEAD_STATE_4(x) (0x0d + (x)) 48 + #define SOR_HEAD_STATE_5(x) (0x0f + (x)) 49 + #define SOR_CRC_CNTRL 0x11 50 + #define SOR_DP_DEBUG_MVID 0x12 51 + 52 + #define SOR_CLK_CNTRL 0x13 53 + #define SOR_CLK_CNTRL_DP_LINK_SPEED_MASK (0x1f << 2) 54 + #define SOR_CLK_CNTRL_DP_LINK_SPEED(x) (((x) & 0x1f) << 2) 55 + #define SOR_CLK_CNTRL_DP_LINK_SPEED_G1_62 (0x06 << 2) 56 + #define SOR_CLK_CNTRL_DP_LINK_SPEED_G2_70 (0x0a << 2) 57 + #define SOR_CLK_CNTRL_DP_LINK_SPEED_G5_40 (0x14 << 2) 58 + #define SOR_CLK_CNTRL_DP_CLK_SEL_MASK (3 << 0) 59 + #define SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_PCLK (0 << 0) 60 + #define SOR_CLK_CNTRL_DP_CLK_SEL_DIFF_PCLK (1 << 0) 61 + #define SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK (2 << 0) 62 + #define SOR_CLK_CNTRL_DP_CLK_SEL_DIFF_DPCLK (3 << 0) 63 + 64 + #define SOR_CAP 0x14 65 + 66 + #define SOR_PWR 0x15 67 + #define SOR_PWR_TRIGGER (1 << 31) 68 + #define SOR_PWR_MODE_SAFE (1 << 28) 69 + #define SOR_PWR_NORMAL_STATE_PU (1 << 0) 70 + 71 + #define SOR_TEST 0x16 72 + #define SOR_TEST_ATTACHED (1 << 10) 73 + #define SOR_TEST_HEAD_MODE_MASK (3 << 8) 74 + #define SOR_TEST_HEAD_MODE_AWAKE (2 << 8) 75 + 76 + #define SOR_PLL_0 0x17 77 + #define SOR_PLL_0_ICHPMP_MASK (0xf << 24) 78 + #define SOR_PLL_0_ICHPMP(x) (((x) & 0xf) << 24) 79 + #define SOR_PLL_0_VCOCAP_MASK (0xf << 8) 80 + #define SOR_PLL_0_VCOCAP(x) (((x) & 0xf) << 8) 81 + #define SOR_PLL_0_VCOCAP_RST SOR_PLL_0_VCOCAP(3) 82 + #define SOR_PLL_0_PLLREG_MASK (0x3 << 6) 83 + #define SOR_PLL_0_PLLREG_LEVEL(x) (((x) & 0x3) << 6) 84 + #define SOR_PLL_0_PLLREG_LEVEL_V25 SOR_PLL_0_PLLREG_LEVEL(0) 85 + #define SOR_PLL_0_PLLREG_LEVEL_V15 SOR_PLL_0_PLLREG_LEVEL(1) 86 + #define SOR_PLL_0_PLLREG_LEVEL_V35 SOR_PLL_0_PLLREG_LEVEL(2) 87 + #define SOR_PLL_0_PLLREG_LEVEL_V45 SOR_PLL_0_PLLREG_LEVEL(3) 88 + #define SOR_PLL_0_PULLDOWN (1 << 5) 89 + #define SOR_PLL_0_RESISTOR_EXT (1 << 4) 90 + #define SOR_PLL_0_VCOPD (1 << 2) 91 + #define SOR_PLL_0_POWER_OFF (1 << 0) 92 + 93 + #define SOR_PLL_1 0x18 94 + /* XXX: read-only bit? */ 95 + #define SOR_PLL_1_TERM_COMPOUT (1 << 15) 96 + #define SOR_PLL_1_TMDS_TERM (1 << 8) 97 + 98 + #define SOR_PLL_2 0x19 99 + #define SOR_PLL_2_LVDS_ENABLE (1 << 25) 100 + #define SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE (1 << 24) 101 + #define SOR_PLL_2_PORT_POWERDOWN (1 << 23) 102 + #define SOR_PLL_2_BANDGAP_POWERDOWN (1 << 22) 103 + #define SOR_PLL_2_POWERDOWN_OVERRIDE (1 << 18) 104 + #define SOR_PLL_2_SEQ_PLLCAPPD (1 << 17) 105 + 106 + #define SOR_PLL_3 0x1a 107 + #define SOR_PLL_3_PLL_VDD_MODE_V1_8 (0 << 13) 108 + #define SOR_PLL_3_PLL_VDD_MODE_V3_3 (1 << 13) 109 + 110 + #define SOR_CSTM 0x1b 111 + #define SOR_CSTM_LVDS (1 << 16) 112 + #define SOR_CSTM_LINK_ACT_B (1 << 15) 113 + #define SOR_CSTM_LINK_ACT_A (1 << 14) 114 + #define SOR_CSTM_UPPER (1 << 11) 115 + 116 + #define SOR_LVDS 0x1c 117 + #define SOR_CRC_A 0x1d 118 + #define SOR_CRC_B 0x1e 119 + #define SOR_BLANK 0x1f 120 + #define SOR_SEQ_CTL 0x20 121 + 122 + #define SOR_LANE_SEQ_CTL 0x21 123 + #define SOR_LANE_SEQ_CTL_TRIGGER (1 << 31) 124 + #define SOR_LANE_SEQ_CTL_SEQUENCE_UP (0 << 20) 125 + #define SOR_LANE_SEQ_CTL_SEQUENCE_DOWN (1 << 20) 126 + #define SOR_LANE_SEQ_CTL_POWER_STATE_UP (0 << 16) 127 + #define SOR_LANE_SEQ_CTL_POWER_STATE_DOWN (1 << 16) 128 + 129 + #define SOR_SEQ_INST(x) (0x22 + (x)) 130 + 131 + #define SOR_PWM_DIV 0x32 132 + #define SOR_PWM_DIV_MASK 0xffffff 133 + 134 + #define SOR_PWM_CTL 0x33 135 + #define SOR_PWM_CTL_TRIGGER (1 << 31) 136 + #define SOR_PWM_CTL_CLK_SEL (1 << 30) 137 + #define SOR_PWM_CTL_DUTY_CYCLE_MASK 0xffffff 138 + 139 + #define SOR_VCRC_A_0 0x34 140 + #define SOR_VCRC_A_1 0x35 141 + #define SOR_VCRC_B_0 0x36 142 + #define SOR_VCRC_B_1 0x37 143 + #define SOR_CCRC_A_0 0x38 144 + #define SOR_CCRC_A_1 0x39 145 + #define SOR_CCRC_B_0 0x3a 146 + #define SOR_CCRC_B_1 0x3b 147 + #define SOR_EDATA_A_0 0x3c 148 + #define SOR_EDATA_A_1 0x3d 149 + #define SOR_EDATA_B_0 0x3e 150 + #define SOR_EDATA_B_1 0x3f 151 + #define SOR_COUNT_A_0 0x40 152 + #define SOR_COUNT_A_1 0x41 153 + #define SOR_COUNT_B_0 0x42 154 + #define SOR_COUNT_B_1 0x43 155 + #define SOR_DEBUG_A_0 0x44 156 + #define SOR_DEBUG_A_1 0x45 157 + #define SOR_DEBUG_B_0 0x46 158 + #define SOR_DEBUG_B_1 0x47 159 + #define SOR_TRIG 0x48 160 + #define SOR_MSCHECK 0x49 161 + #define SOR_XBAR_CTRL 0x4a 162 + #define SOR_XBAR_POL 0x4b 163 + 164 + #define SOR_DP_LINKCTL_0 0x4c 165 + #define SOR_DP_LINKCTL_LANE_COUNT_MASK (0x1f << 16) 166 + #define SOR_DP_LINKCTL_LANE_COUNT(x) (((1 << (x)) - 1) << 16) 167 + #define SOR_DP_LINKCTL_ENHANCED_FRAME (1 << 14) 168 + #define SOR_DP_LINKCTL_TU_SIZE_MASK (0x7f << 2) 169 + #define SOR_DP_LINKCTL_TU_SIZE(x) (((x) & 0x7f) << 2) 170 + #define SOR_DP_LINKCTL_ENABLE (1 << 0) 171 + 172 + #define SOR_DP_LINKCTL_1 0x4d 173 + 174 + #define SOR_LANE_DRIVE_CURRENT_0 0x4e 175 + #define SOR_LANE_DRIVE_CURRENT_1 0x4f 176 + #define SOR_LANE4_DRIVE_CURRENT_0 0x50 177 + #define SOR_LANE4_DRIVE_CURRENT_1 0x51 178 + #define SOR_LANE_DRIVE_CURRENT_LANE3(x) (((x) & 0xff) << 24) 179 + #define SOR_LANE_DRIVE_CURRENT_LANE2(x) (((x) & 0xff) << 16) 180 + #define SOR_LANE_DRIVE_CURRENT_LANE1(x) (((x) & 0xff) << 8) 181 + #define SOR_LANE_DRIVE_CURRENT_LANE0(x) (((x) & 0xff) << 0) 182 + 183 + #define SOR_LANE_PREEMPHASIS_0 0x52 184 + #define SOR_LANE_PREEMPHASIS_1 0x53 185 + #define SOR_LANE4_PREEMPHASIS_0 0x54 186 + #define SOR_LANE4_PREEMPHASIS_1 0x55 187 + #define SOR_LANE_PREEMPHASIS_LANE3(x) (((x) & 0xff) << 24) 188 + #define SOR_LANE_PREEMPHASIS_LANE2(x) (((x) & 0xff) << 16) 189 + #define SOR_LANE_PREEMPHASIS_LANE1(x) (((x) & 0xff) << 8) 190 + #define SOR_LANE_PREEMPHASIS_LANE0(x) (((x) & 0xff) << 0) 191 + 192 + #define SOR_LANE_POST_CURSOR_0 0x56 193 + #define SOR_LANE_POST_CURSOR_1 0x57 194 + #define SOR_LANE_POST_CURSOR_LANE3(x) (((x) & 0xff) << 24) 195 + #define SOR_LANE_POST_CURSOR_LANE2(x) (((x) & 0xff) << 16) 196 + #define SOR_LANE_POST_CURSOR_LANE1(x) (((x) & 0xff) << 8) 197 + #define SOR_LANE_POST_CURSOR_LANE0(x) (((x) & 0xff) << 0) 198 + 199 + #define SOR_DP_CONFIG_0 0x58 200 + #define SOR_DP_CONFIG_DISPARITY_NEGATIVE (1 << 31) 201 + #define SOR_DP_CONFIG_ACTIVE_SYM_ENABLE (1 << 26) 202 + #define SOR_DP_CONFIG_ACTIVE_SYM_POLARITY (1 << 24) 203 + #define SOR_DP_CONFIG_ACTIVE_SYM_FRAC_MASK (0xf << 16) 204 + #define SOR_DP_CONFIG_ACTIVE_SYM_FRAC(x) (((x) & 0xf) << 16) 205 + #define SOR_DP_CONFIG_ACTIVE_SYM_COUNT_MASK (0x7f << 8) 206 + #define SOR_DP_CONFIG_ACTIVE_SYM_COUNT(x) (((x) & 0x7f) << 8) 207 + #define SOR_DP_CONFIG_WATERMARK_MASK (0x3f << 0) 208 + #define SOR_DP_CONFIG_WATERMARK(x) (((x) & 0x3f) << 0) 209 + 210 + #define SOR_DP_CONFIG_1 0x59 211 + #define SOR_DP_MN_0 0x5a 212 + #define SOR_DP_MN_1 0x5b 213 + 214 + #define SOR_DP_PADCTL_0 0x5c 215 + #define SOR_DP_PADCTL_PAD_CAL_PD (1 << 23) 216 + #define SOR_DP_PADCTL_TX_PU_ENABLE (1 << 22) 217 + #define SOR_DP_PADCTL_TX_PU_MASK (0xff << 8) 218 + #define SOR_DP_PADCTL_TX_PU(x) (((x) & 0xff) << 8) 219 + #define SOR_DP_PADCTL_CM_TXD_3 (1 << 7) 220 + #define SOR_DP_PADCTL_CM_TXD_2 (1 << 6) 221 + #define SOR_DP_PADCTL_CM_TXD_1 (1 << 5) 222 + #define SOR_DP_PADCTL_CM_TXD_0 (1 << 4) 223 + #define SOR_DP_PADCTL_PD_TXD_3 (1 << 3) 224 + #define SOR_DP_PADCTL_PD_TXD_0 (1 << 2) 225 + #define SOR_DP_PADCTL_PD_TXD_1 (1 << 1) 226 + #define SOR_DP_PADCTL_PD_TXD_2 (1 << 0) 227 + 228 + #define SOR_DP_PADCTL_1 0x5d 229 + 230 + #define SOR_DP_DEBUG_0 0x5e 231 + #define SOR_DP_DEBUG_1 0x5f 232 + 233 + #define SOR_DP_SPARE_0 0x60 234 + #define SOR_DP_SPARE_MACRO_SOR_CLK (1 << 2) 235 + #define SOR_DP_SPARE_PANEL_INTERNAL (1 << 1) 236 + #define SOR_DP_SPARE_SEQ_ENABLE (1 << 0) 237 + 238 + #define SOR_DP_SPARE_1 0x61 239 + #define SOR_DP_AUDIO_CTRL 0x62 240 + 241 + #define SOR_DP_AUDIO_HBLANK_SYMBOLS 0x63 242 + #define SOR_DP_AUDIO_HBLANK_SYMBOLS_MASK (0x01ffff << 0) 243 + 244 + #define SOR_DP_AUDIO_VBLANK_SYMBOLS 0x64 245 + #define SOR_DP_AUDIO_VBLANK_SYMBOLS_MASK (0x1fffff << 0) 246 + 247 + #define SOR_DP_GENERIC_INFOFRAME_HEADER 0x65 248 + #define SOR_DP_GENERIC_INFOFRAME_SUBPACK_0 0x66 249 + #define SOR_DP_GENERIC_INFOFRAME_SUBPACK_1 0x67 250 + #define SOR_DP_GENERIC_INFOFRAME_SUBPACK_2 0x68 251 + #define SOR_DP_GENERIC_INFOFRAME_SUBPACK_3 0x69 252 + #define SOR_DP_GENERIC_INFOFRAME_SUBPACK_4 0x6a 253 + #define SOR_DP_GENERIC_INFOFRAME_SUBPACK_5 0x6b 254 + #define SOR_DP_GENERIC_INFOFRAME_SUBPACK_6 0x6c 255 + 256 + #define SOR_DP_TPG 0x6d 257 + #define SOR_DP_TPG_CHANNEL_CODING (1 << 6) 258 + #define SOR_DP_TPG_SCRAMBLER_MASK (3 << 4) 259 + #define SOR_DP_TPG_SCRAMBLER_FIBONACCI (2 << 4) 260 + #define SOR_DP_TPG_SCRAMBLER_GALIOS (1 << 4) 261 + #define SOR_DP_TPG_SCRAMBLER_NONE (0 << 4) 262 + #define SOR_DP_TPG_PATTERN_MASK (0xf << 0) 263 + #define SOR_DP_TPG_PATTERN_HBR2 (0x8 << 0) 264 + #define SOR_DP_TPG_PATTERN_CSTM (0x7 << 0) 265 + #define SOR_DP_TPG_PATTERN_PRBS7 (0x6 << 0) 266 + #define SOR_DP_TPG_PATTERN_SBLERRRATE (0x5 << 0) 267 + #define SOR_DP_TPG_PATTERN_D102 (0x4 << 0) 268 + #define SOR_DP_TPG_PATTERN_TRAIN3 (0x3 << 0) 269 + #define SOR_DP_TPG_PATTERN_TRAIN2 (0x2 << 0) 270 + #define SOR_DP_TPG_PATTERN_TRAIN1 (0x1 << 0) 271 + #define SOR_DP_TPG_PATTERN_NONE (0x0 << 0) 272 + 273 + #define SOR_DP_TPG_CONFIG 0x6e 274 + #define SOR_DP_LQ_CSTM_0 0x6f 275 + #define SOR_DP_LQ_CSTM_1 0x70 276 + #define SOR_DP_LQ_CSTM_2 0x71 277 + 278 + #endif
+1
drivers/gpu/host1x/syncpt.c
··· 102 102 { 103 103 return (u32)atomic_add_return(incrs, &sp->max_val); 104 104 } 105 + EXPORT_SYMBOL(host1x_syncpt_incr_max); 105 106 106 107 /* 107 108 * Write cached syncpoint and waitbase values to hardware.
+1
include/linux/host1x.h
··· 136 136 u32 host1x_syncpt_read_min(struct host1x_syncpt *sp); 137 137 u32 host1x_syncpt_read_max(struct host1x_syncpt *sp); 138 138 int host1x_syncpt_incr(struct host1x_syncpt *sp); 139 + u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs); 139 140 int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout, 140 141 u32 *value); 141 142 struct host1x_syncpt *host1x_syncpt_request(struct device *dev,
+15 -9
include/uapi/drm/tegra_drm.h
··· 1 1 /* 2 2 * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved. 3 3 * 4 - * This program is free software; you can redistribute it and/or modify it 5 - * under the terms and conditions of the GNU General Public License, 6 - * version 2, as published by the Free Software Foundation. 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 7 10 * 8 - * This program is distributed in the hope it will be useful, but WITHOUT 9 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 - * more details. 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 12 13 * 13 - * You should have received a copy of the GNU General Public License 14 - * along with this program. If not, see <http://www.gnu.org/licenses/>. 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 15 21 */ 16 22 17 23 #ifndef _UAPI_TEGRA_DRM_H_