sorgf119.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /*
  2. * Copyright 2012 Red Hat Inc.
  3. *
  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:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  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.
  21. *
  22. * Authors: Ben Skeggs
  23. */
  24. #include "nv50.h"
  25. #include "outpdp.h"
  26. static inline u32
  27. gf119_sor_soff(struct nvkm_output_dp *outp)
  28. {
  29. return (ffs(outp->base.info.or) - 1) * 0x800;
  30. }
  31. static inline u32
  32. gf119_sor_loff(struct nvkm_output_dp *outp)
  33. {
  34. return gf119_sor_soff(outp) + !(outp->base.info.sorconf.link & 1) * 0x80;
  35. }
  36. static int
  37. gf119_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern)
  38. {
  39. struct nvkm_device *device = outp->base.disp->engine.subdev.device;
  40. const u32 loff = gf119_sor_loff(outp);
  41. nvkm_mask(device, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * pattern);
  42. return 0;
  43. }
  44. int
  45. gf119_sor_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef)
  46. {
  47. struct nvkm_device *device = outp->base.disp->engine.subdev.device;
  48. const u32 soff = gf119_sor_soff(outp);
  49. const u32 loff = gf119_sor_loff(outp);
  50. u32 dpctrl = 0x00000000;
  51. u32 clksor = 0x00000000;
  52. clksor |= bw << 18;
  53. dpctrl |= ((1 << nr) - 1) << 16;
  54. if (ef)
  55. dpctrl |= 0x00004000;
  56. nvkm_mask(device, 0x612300 + soff, 0x007c0000, clksor);
  57. nvkm_mask(device, 0x61c10c + loff, 0x001f4000, dpctrl);
  58. return 0;
  59. }
  60. static int
  61. gf119_sor_dp_drv_ctl(struct nvkm_output_dp *outp,
  62. int ln, int vs, int pe, int pc)
  63. {
  64. struct nvkm_device *device = outp->base.disp->engine.subdev.device;
  65. struct nvkm_bios *bios = device->bios;
  66. const u32 shift = g94_sor_dp_lane_map(device, ln);
  67. const u32 loff = gf119_sor_loff(outp);
  68. u32 addr, data[4];
  69. u8 ver, hdr, cnt, len;
  70. struct nvbios_dpout info;
  71. struct nvbios_dpcfg ocfg;
  72. addr = nvbios_dpout_match(bios, outp->base.info.hasht,
  73. outp->base.info.hashm,
  74. &ver, &hdr, &cnt, &len, &info);
  75. if (!addr)
  76. return -ENODEV;
  77. addr = nvbios_dpcfg_match(bios, addr, pc, vs, pe,
  78. &ver, &hdr, &cnt, &len, &ocfg);
  79. if (!addr)
  80. return -EINVAL;
  81. data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift);
  82. data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift);
  83. data[2] = nvkm_rd32(device, 0x61c130 + loff);
  84. if ((data[2] & 0x0000ff00) < (ocfg.tx_pu << 8) || ln == 0)
  85. data[2] = (data[2] & ~0x0000ff00) | (ocfg.tx_pu << 8);
  86. nvkm_wr32(device, 0x61c118 + loff, data[0] | (ocfg.dc << shift));
  87. nvkm_wr32(device, 0x61c120 + loff, data[1] | (ocfg.pe << shift));
  88. nvkm_wr32(device, 0x61c130 + loff, data[2]);
  89. data[3] = nvkm_rd32(device, 0x61c13c + loff) & ~(0x000000ff << shift);
  90. nvkm_wr32(device, 0x61c13c + loff, data[3] | (ocfg.pc << shift));
  91. return 0;
  92. }
  93. static const struct nvkm_output_dp_func
  94. gf119_sor_dp_func = {
  95. .pattern = gf119_sor_dp_pattern,
  96. .lnk_pwr = g94_sor_dp_lnk_pwr,
  97. .lnk_ctl = gf119_sor_dp_lnk_ctl,
  98. .drv_ctl = gf119_sor_dp_drv_ctl,
  99. };
  100. int
  101. gf119_sor_dp_new(struct nvkm_disp *disp, int index,
  102. struct dcb_output *dcbE, struct nvkm_output **poutp)
  103. {
  104. return nvkm_output_dp_new_(&gf119_sor_dp_func, disp, index, dcbE, poutp);
  105. }