nv50.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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 nv50_devinit *init = nv50_devinit(base);
  87. struct nvkm_subdev *subdev = &init->base.subdev;
  88. struct nvkm_device *device = subdev->device;
  89. /* our heuristics can't detect whether the board has had its
  90. * devinit scripts executed or not if the display engine is
  91. * missing, assume it's a secondary gpu which requires post
  92. */
  93. if (!init->base.post) {
  94. u64 disable = nvkm_devinit_disable(&init->base);
  95. if (disable & (1ULL << NVKM_ENGINE_DISP))
  96. init->base.post = true;
  97. }
  98. /* magic to detect whether or not x86 vbios code has executed
  99. * the devinit scripts to initialise the board
  100. */
  101. if (!init->base.post) {
  102. if (!nvkm_rdvgac(device, 0, 0x00) &&
  103. !nvkm_rdvgac(device, 0, 0x1a)) {
  104. nvkm_debug(subdev, "adaptor not initialised\n");
  105. init->base.post = true;
  106. }
  107. }
  108. }
  109. void
  110. nv50_devinit_init(struct nvkm_devinit *base)
  111. {
  112. struct nv50_devinit *init = nv50_devinit(base);
  113. struct nvkm_subdev *subdev = &init->base.subdev;
  114. struct nvkm_device *device = subdev->device;
  115. struct nvkm_bios *bios = device->bios;
  116. struct nvbios_outp info;
  117. struct dcb_output outp;
  118. u8 ver = 0xff, hdr, cnt, len;
  119. int i = 0;
  120. /* if we ran the init tables, we have to execute the first script
  121. * pointer of each dcb entry's display encoder table in order
  122. * to properly initialise each encoder.
  123. */
  124. while (init->base.post && dcb_outp_parse(bios, i, &ver, &hdr, &outp)) {
  125. if (nvbios_outp_match(bios, outp.hasht, outp.hashm,
  126. &ver, &hdr, &cnt, &len, &info)) {
  127. struct nvbios_init exec = {
  128. .subdev = subdev,
  129. .bios = bios,
  130. .offset = info.script[0],
  131. .outp = &outp,
  132. .crtc = -1,
  133. .execute = 1,
  134. };
  135. nvbios_exec(&exec);
  136. }
  137. i++;
  138. }
  139. }
  140. int
  141. nv50_devinit_new_(const struct nvkm_devinit_func *func,
  142. struct nvkm_device *device, int index,
  143. struct nvkm_devinit **pinit)
  144. {
  145. struct nv50_devinit *init;
  146. if (!(init = kzalloc(sizeof(*init), GFP_KERNEL)))
  147. return -ENOMEM;
  148. *pinit = &init->base;
  149. nvkm_devinit_ctor(func, device, index, &init->base);
  150. return 0;
  151. }
  152. static const struct nvkm_devinit_func
  153. nv50_devinit = {
  154. .preinit = nv50_devinit_preinit,
  155. .init = nv50_devinit_init,
  156. .post = nv04_devinit_post,
  157. .pll_set = nv50_devinit_pll_set,
  158. .disable = nv50_devinit_disable,
  159. };
  160. int
  161. nv50_devinit_new(struct nvkm_device *device, int index,
  162. struct nvkm_devinit **pinit)
  163. {
  164. return nv50_devinit_new_(&nv50_devinit, device, index, pinit);
  165. }