nv50.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*
  2. * Copyright 2013 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 <subdev/bios.h>
  26. #include <subdev/bios/dcb.h>
  27. #include <subdev/bios/disp.h>
  28. #include <subdev/bios/init.h>
  29. #include <subdev/bios/pll.h>
  30. #include <subdev/clk/pll.h>
  31. #include <subdev/vga.h>
  32. int
  33. nv50_devinit_pll_set(struct nvkm_devinit *init, u32 type, u32 freq)
  34. {
  35. struct nvkm_subdev *subdev = &init->subdev;
  36. struct nvkm_device *device = subdev->device;
  37. struct nvkm_bios *bios = device->bios;
  38. struct nvbios_pll info;
  39. int N1, M1, N2, M2, P;
  40. int ret;
  41. ret = nvbios_pll_parse(bios, type, &info);
  42. if (ret) {
  43. nvkm_error(subdev, "failed to retrieve pll data, %d\n", ret);
  44. return ret;
  45. }
  46. ret = nv04_pll_calc(subdev, &info, freq, &N1, &M1, &N2, &M2, &P);
  47. if (!ret) {
  48. nvkm_error(subdev, "failed pll calculation\n");
  49. return ret;
  50. }
  51. switch (info.type) {
  52. case PLL_VPLL0:
  53. case PLL_VPLL1:
  54. nvkm_wr32(device, info.reg + 0, 0x10000611);
  55. nvkm_mask(device, info.reg + 4, 0x00ff00ff, (M1 << 16) | N1);
  56. nvkm_mask(device, info.reg + 8, 0x7fff00ff, (P << 28) |
  57. (M2 << 16) | N2);
  58. break;
  59. case PLL_MEMORY:
  60. nvkm_mask(device, info.reg + 0, 0x01ff0000,
  61. (P << 22) |
  62. (info.bias_p << 19) |
  63. (P << 16));
  64. nvkm_wr32(device, info.reg + 4, (N1 << 8) | M1);
  65. break;
  66. default:
  67. nvkm_mask(device, info.reg + 0, 0x00070000, (P << 16));
  68. nvkm_wr32(device, info.reg + 4, (N1 << 8) | M1);
  69. break;
  70. }
  71. return 0;
  72. }
  73. static u64
  74. nv50_devinit_disable(struct nvkm_devinit *init)
  75. {
  76. struct nvkm_device *device = init->subdev.device;
  77. u32 r001540 = nvkm_rd32(device, 0x001540);
  78. u64 disable = 0ULL;
  79. if (!(r001540 & 0x40000000))
  80. disable |= (1ULL << NVKM_ENGINE_MPEG);
  81. return disable;
  82. }
  83. void
  84. nv50_devinit_preinit(struct nvkm_devinit *base)
  85. {
  86. struct nvkm_subdev *subdev = &base->subdev;
  87. struct nvkm_device *device = subdev->device;
  88. /* our heuristics can't detect whether the board has had its
  89. * devinit scripts executed or not if the display engine is
  90. * missing, assume it's a secondary gpu which requires post
  91. */
  92. if (!base->post) {
  93. u64 disable = nvkm_devinit_disable(base);
  94. if (disable & (1ULL << NVKM_ENGINE_DISP))
  95. base->post = true;
  96. }
  97. /* magic to detect whether or not x86 vbios code has executed
  98. * the devinit scripts to initialise the board
  99. */
  100. if (!base->post) {
  101. if (!nvkm_rdvgac(device, 0, 0x00) &&
  102. !nvkm_rdvgac(device, 0, 0x1a)) {
  103. nvkm_debug(subdev, "adaptor not initialised\n");
  104. base->post = true;
  105. }
  106. }
  107. }
  108. void
  109. nv50_devinit_init(struct nvkm_devinit *base)
  110. {
  111. struct nv50_devinit *init = nv50_devinit(base);
  112. struct nvkm_subdev *subdev = &init->base.subdev;
  113. struct nvkm_device *device = subdev->device;
  114. struct nvkm_bios *bios = device->bios;
  115. struct nvbios_outp info;
  116. struct dcb_output outp;
  117. u8 ver = 0xff, hdr, cnt, len;
  118. int i = 0;
  119. /* if we ran the init tables, we have to execute the first script
  120. * pointer of each dcb entry's display encoder table in order
  121. * to properly initialise each encoder.
  122. */
  123. while (init->base.post && dcb_outp_parse(bios, i, &ver, &hdr, &outp)) {
  124. if (nvbios_outp_match(bios, outp.hasht, outp.hashm,
  125. &ver, &hdr, &cnt, &len, &info)) {
  126. struct nvbios_init exec = {
  127. .subdev = subdev,
  128. .bios = bios,
  129. .offset = info.script[0],
  130. .outp = &outp,
  131. .crtc = -1,
  132. .execute = 1,
  133. };
  134. nvbios_exec(&exec);
  135. }
  136. i++;
  137. }
  138. }
  139. int
  140. nv50_devinit_new_(const struct nvkm_devinit_func *func,
  141. struct nvkm_device *device, int index,
  142. struct nvkm_devinit **pinit)
  143. {
  144. struct nv50_devinit *init;
  145. if (!(init = kzalloc(sizeof(*init), GFP_KERNEL)))
  146. return -ENOMEM;
  147. *pinit = &init->base;
  148. nvkm_devinit_ctor(func, device, index, &init->base);
  149. return 0;
  150. }
  151. static const struct nvkm_devinit_func
  152. nv50_devinit = {
  153. .preinit = nv50_devinit_preinit,
  154. .init = nv50_devinit_init,
  155. .post = nv04_devinit_post,
  156. .pll_set = nv50_devinit_pll_set,
  157. .disable = nv50_devinit_disable,
  158. };
  159. int
  160. nv50_devinit_new(struct nvkm_device *device, int index,
  161. struct nvkm_devinit **pinit)
  162. {
  163. return nv50_devinit_new_(&nv50_devinit, device, index, pinit);
  164. }