gf119.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  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 "rootnv50.h"
  26. #include <subdev/bios.h>
  27. #include <subdev/bios/disp.h>
  28. #include <subdev/bios/init.h>
  29. #include <subdev/bios/pll.h>
  30. #include <subdev/devinit.h>
  31. void
  32. gf119_disp_vblank_init(struct nv50_disp *disp, int head)
  33. {
  34. struct nvkm_device *device = disp->base.engine.subdev.device;
  35. nvkm_mask(device, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000001);
  36. }
  37. void
  38. gf119_disp_vblank_fini(struct nv50_disp *disp, int head)
  39. {
  40. struct nvkm_device *device = disp->base.engine.subdev.device;
  41. nvkm_mask(device, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000000);
  42. }
  43. static struct nvkm_output *
  44. exec_lookup(struct nv50_disp *disp, int head, int or, u32 ctrl,
  45. u32 *data, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
  46. struct nvbios_outp *info)
  47. {
  48. struct nvkm_subdev *subdev = &disp->base.engine.subdev;
  49. struct nvkm_bios *bios = subdev->device->bios;
  50. struct nvkm_output *outp;
  51. u16 mask, type;
  52. if (or < 4) {
  53. type = DCB_OUTPUT_ANALOG;
  54. mask = 0;
  55. } else {
  56. or -= 4;
  57. switch (ctrl & 0x00000f00) {
  58. case 0x00000000: type = DCB_OUTPUT_LVDS; mask = 1; break;
  59. case 0x00000100: type = DCB_OUTPUT_TMDS; mask = 1; break;
  60. case 0x00000200: type = DCB_OUTPUT_TMDS; mask = 2; break;
  61. case 0x00000500: type = DCB_OUTPUT_TMDS; mask = 3; break;
  62. case 0x00000800: type = DCB_OUTPUT_DP; mask = 1; break;
  63. case 0x00000900: type = DCB_OUTPUT_DP; mask = 2; break;
  64. default:
  65. nvkm_error(subdev, "unknown SOR mc %08x\n", ctrl);
  66. return NULL;
  67. }
  68. }
  69. mask = 0x00c0 & (mask << 6);
  70. mask |= 0x0001 << or;
  71. mask |= 0x0100 << head;
  72. list_for_each_entry(outp, &disp->base.outp, head) {
  73. if ((outp->info.hasht & 0xff) == type &&
  74. (outp->info.hashm & mask) == mask) {
  75. *data = nvbios_outp_match(bios, outp->info.hasht,
  76. outp->info.hashm,
  77. ver, hdr, cnt, len, info);
  78. if (!*data)
  79. return NULL;
  80. return outp;
  81. }
  82. }
  83. return NULL;
  84. }
  85. static struct nvkm_output *
  86. exec_script(struct nv50_disp *disp, int head, int id)
  87. {
  88. struct nvkm_subdev *subdev = &disp->base.engine.subdev;
  89. struct nvkm_device *device = subdev->device;
  90. struct nvkm_bios *bios = device->bios;
  91. struct nvkm_output *outp;
  92. struct nvbios_outp info;
  93. u8 ver, hdr, cnt, len;
  94. u32 data, ctrl = 0;
  95. int or;
  96. for (or = 0; !(ctrl & (1 << head)) && or < 8; or++) {
  97. ctrl = nvkm_rd32(device, 0x640180 + (or * 0x20));
  98. if (ctrl & (1 << head))
  99. break;
  100. }
  101. if (or == 8)
  102. return NULL;
  103. outp = exec_lookup(disp, head, or, ctrl, &data, &ver, &hdr, &cnt, &len, &info);
  104. if (outp) {
  105. struct nvbios_init init = {
  106. .subdev = subdev,
  107. .bios = bios,
  108. .offset = info.script[id],
  109. .outp = &outp->info,
  110. .crtc = head,
  111. .execute = 1,
  112. };
  113. nvbios_exec(&init);
  114. }
  115. return outp;
  116. }
  117. static struct nvkm_output *
  118. exec_clkcmp(struct nv50_disp *disp, int head, int id, u32 pclk, u32 *conf)
  119. {
  120. struct nvkm_subdev *subdev = &disp->base.engine.subdev;
  121. struct nvkm_device *device = subdev->device;
  122. struct nvkm_bios *bios = device->bios;
  123. struct nvkm_output *outp;
  124. struct nvbios_outp info1;
  125. struct nvbios_ocfg info2;
  126. u8 ver, hdr, cnt, len;
  127. u32 data, ctrl = 0;
  128. int or;
  129. for (or = 0; !(ctrl & (1 << head)) && or < 8; or++) {
  130. ctrl = nvkm_rd32(device, 0x660180 + (or * 0x20));
  131. if (ctrl & (1 << head))
  132. break;
  133. }
  134. if (or == 8)
  135. return NULL;
  136. outp = exec_lookup(disp, head, or, ctrl, &data, &ver, &hdr, &cnt, &len, &info1);
  137. if (!outp)
  138. return NULL;
  139. switch (outp->info.type) {
  140. case DCB_OUTPUT_TMDS:
  141. *conf = (ctrl & 0x00000f00) >> 8;
  142. if (pclk >= 165000)
  143. *conf |= 0x0100;
  144. break;
  145. case DCB_OUTPUT_LVDS:
  146. *conf = disp->sor.lvdsconf;
  147. break;
  148. case DCB_OUTPUT_DP:
  149. *conf = (ctrl & 0x00000f00) >> 8;
  150. break;
  151. case DCB_OUTPUT_ANALOG:
  152. default:
  153. *conf = 0x00ff;
  154. break;
  155. }
  156. data = nvbios_ocfg_match(bios, data, *conf, &ver, &hdr, &cnt, &len, &info2);
  157. if (data && id < 0xff) {
  158. data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
  159. if (data) {
  160. struct nvbios_init init = {
  161. .subdev = subdev,
  162. .bios = bios,
  163. .offset = data,
  164. .outp = &outp->info,
  165. .crtc = head,
  166. .execute = 1,
  167. };
  168. nvbios_exec(&init);
  169. }
  170. }
  171. return outp;
  172. }
  173. static void
  174. gf119_disp_intr_unk1_0(struct nv50_disp *disp, int head)
  175. {
  176. exec_script(disp, head, 1);
  177. }
  178. static void
  179. gf119_disp_intr_unk2_0(struct nv50_disp *disp, int head)
  180. {
  181. struct nvkm_subdev *subdev = &disp->base.engine.subdev;
  182. struct nvkm_output *outp = exec_script(disp, head, 2);
  183. /* see note in nv50_disp_intr_unk20_0() */
  184. if (outp && outp->info.type == DCB_OUTPUT_DP) {
  185. struct nvkm_output_dp *outpdp = nvkm_output_dp(outp);
  186. struct nvbios_init init = {
  187. .subdev = subdev,
  188. .bios = subdev->device->bios,
  189. .outp = &outp->info,
  190. .crtc = head,
  191. .offset = outpdp->info.script[4],
  192. .execute = 1,
  193. };
  194. nvbios_exec(&init);
  195. atomic_set(&outpdp->lt.done, 0);
  196. }
  197. }
  198. static void
  199. gf119_disp_intr_unk2_1(struct nv50_disp *disp, int head)
  200. {
  201. struct nvkm_device *device = disp->base.engine.subdev.device;
  202. struct nvkm_devinit *devinit = device->devinit;
  203. u32 pclk = nvkm_rd32(device, 0x660450 + (head * 0x300)) / 1000;
  204. if (pclk)
  205. nvkm_devinit_pll_set(devinit, PLL_VPLL0 + head, pclk);
  206. nvkm_wr32(device, 0x612200 + (head * 0x800), 0x00000000);
  207. }
  208. static void
  209. gf119_disp_intr_unk2_2_tu(struct nv50_disp *disp, int head,
  210. struct dcb_output *outp)
  211. {
  212. struct nvkm_device *device = disp->base.engine.subdev.device;
  213. const int or = ffs(outp->or) - 1;
  214. const u32 ctrl = nvkm_rd32(device, 0x660200 + (or * 0x020));
  215. const u32 conf = nvkm_rd32(device, 0x660404 + (head * 0x300));
  216. const s32 vactive = nvkm_rd32(device, 0x660414 + (head * 0x300)) & 0xffff;
  217. const s32 vblanke = nvkm_rd32(device, 0x66041c + (head * 0x300)) & 0xffff;
  218. const s32 vblanks = nvkm_rd32(device, 0x660420 + (head * 0x300)) & 0xffff;
  219. const u32 pclk = nvkm_rd32(device, 0x660450 + (head * 0x300)) / 1000;
  220. const u32 link = ((ctrl & 0xf00) == 0x800) ? 0 : 1;
  221. const u32 hoff = (head * 0x800);
  222. const u32 soff = ( or * 0x800);
  223. const u32 loff = (link * 0x080) + soff;
  224. const u32 symbol = 100000;
  225. const u32 TU = 64;
  226. u32 dpctrl = nvkm_rd32(device, 0x61c10c + loff);
  227. u32 clksor = nvkm_rd32(device, 0x612300 + soff);
  228. u32 datarate, link_nr, link_bw, bits;
  229. u64 ratio, value;
  230. link_nr = hweight32(dpctrl & 0x000f0000);
  231. link_bw = (clksor & 0x007c0000) >> 18;
  232. link_bw *= 27000;
  233. /* symbols/hblank - algorithm taken from comments in tegra driver */
  234. value = vblanke + vactive - vblanks - 7;
  235. value = value * link_bw;
  236. do_div(value, pclk);
  237. value = value - (3 * !!(dpctrl & 0x00004000)) - (12 / link_nr);
  238. nvkm_mask(device, 0x616620 + hoff, 0x0000ffff, value);
  239. /* symbols/vblank - algorithm taken from comments in tegra driver */
  240. value = vblanks - vblanke - 25;
  241. value = value * link_bw;
  242. do_div(value, pclk);
  243. value = value - ((36 / link_nr) + 3) - 1;
  244. nvkm_mask(device, 0x616624 + hoff, 0x00ffffff, value);
  245. /* watermark */
  246. if ((conf & 0x3c0) == 0x180) bits = 30;
  247. else if ((conf & 0x3c0) == 0x140) bits = 24;
  248. else bits = 18;
  249. datarate = (pclk * bits) / 8;
  250. ratio = datarate;
  251. ratio *= symbol;
  252. do_div(ratio, link_nr * link_bw);
  253. value = (symbol - ratio) * TU;
  254. value *= ratio;
  255. do_div(value, symbol);
  256. do_div(value, symbol);
  257. value += 5;
  258. value |= 0x08000000;
  259. nvkm_wr32(device, 0x616610 + hoff, value);
  260. }
  261. static void
  262. gf119_disp_intr_unk2_2(struct nv50_disp *disp, int head)
  263. {
  264. struct nvkm_device *device = disp->base.engine.subdev.device;
  265. struct nvkm_output *outp;
  266. u32 pclk = nvkm_rd32(device, 0x660450 + (head * 0x300)) / 1000;
  267. u32 conf, addr, data;
  268. outp = exec_clkcmp(disp, head, 0xff, pclk, &conf);
  269. if (!outp)
  270. return;
  271. /* see note in nv50_disp_intr_unk20_2() */
  272. if (outp->info.type == DCB_OUTPUT_DP) {
  273. u32 sync = nvkm_rd32(device, 0x660404 + (head * 0x300));
  274. switch ((sync & 0x000003c0) >> 6) {
  275. case 6: pclk = pclk * 30; break;
  276. case 5: pclk = pclk * 24; break;
  277. case 2:
  278. default:
  279. pclk = pclk * 18;
  280. break;
  281. }
  282. if (nvkm_output_dp_train(outp, pclk, true))
  283. OUTP_ERR(outp, "link not trained before attach");
  284. } else {
  285. if (disp->func->sor.magic)
  286. disp->func->sor.magic(outp);
  287. }
  288. exec_clkcmp(disp, head, 0, pclk, &conf);
  289. if (outp->info.type == DCB_OUTPUT_ANALOG) {
  290. addr = 0x612280 + (ffs(outp->info.or) - 1) * 0x800;
  291. data = 0x00000000;
  292. } else {
  293. addr = 0x612300 + (ffs(outp->info.or) - 1) * 0x800;
  294. data = (conf & 0x0100) ? 0x00000101 : 0x00000000;
  295. switch (outp->info.type) {
  296. case DCB_OUTPUT_TMDS:
  297. nvkm_mask(device, addr, 0x007c0000, 0x00280000);
  298. break;
  299. case DCB_OUTPUT_DP:
  300. gf119_disp_intr_unk2_2_tu(disp, head, &outp->info);
  301. break;
  302. default:
  303. break;
  304. }
  305. }
  306. nvkm_mask(device, addr, 0x00000707, data);
  307. }
  308. static void
  309. gf119_disp_intr_unk4_0(struct nv50_disp *disp, int head)
  310. {
  311. struct nvkm_device *device = disp->base.engine.subdev.device;
  312. u32 pclk = nvkm_rd32(device, 0x660450 + (head * 0x300)) / 1000;
  313. u32 conf;
  314. exec_clkcmp(disp, head, 1, pclk, &conf);
  315. }
  316. void
  317. gf119_disp_intr_supervisor(struct work_struct *work)
  318. {
  319. struct nv50_disp *disp =
  320. container_of(work, struct nv50_disp, supervisor);
  321. struct nvkm_subdev *subdev = &disp->base.engine.subdev;
  322. struct nvkm_device *device = subdev->device;
  323. u32 mask[4];
  324. int head;
  325. nvkm_debug(subdev, "supervisor %d\n", ffs(disp->super));
  326. for (head = 0; head < disp->base.head.nr; head++) {
  327. mask[head] = nvkm_rd32(device, 0x6101d4 + (head * 0x800));
  328. nvkm_debug(subdev, "head %d: %08x\n", head, mask[head]);
  329. }
  330. if (disp->super & 0x00000001) {
  331. nv50_disp_chan_mthd(disp->chan[0], NV_DBG_DEBUG);
  332. for (head = 0; head < disp->base.head.nr; head++) {
  333. if (!(mask[head] & 0x00001000))
  334. continue;
  335. nvkm_debug(subdev, "supervisor 1.0 - head %d\n", head);
  336. gf119_disp_intr_unk1_0(disp, head);
  337. }
  338. } else
  339. if (disp->super & 0x00000002) {
  340. for (head = 0; head < disp->base.head.nr; head++) {
  341. if (!(mask[head] & 0x00001000))
  342. continue;
  343. nvkm_debug(subdev, "supervisor 2.0 - head %d\n", head);
  344. gf119_disp_intr_unk2_0(disp, head);
  345. }
  346. for (head = 0; head < disp->base.head.nr; head++) {
  347. if (!(mask[head] & 0x00010000))
  348. continue;
  349. nvkm_debug(subdev, "supervisor 2.1 - head %d\n", head);
  350. gf119_disp_intr_unk2_1(disp, head);
  351. }
  352. for (head = 0; head < disp->base.head.nr; head++) {
  353. if (!(mask[head] & 0x00001000))
  354. continue;
  355. nvkm_debug(subdev, "supervisor 2.2 - head %d\n", head);
  356. gf119_disp_intr_unk2_2(disp, head);
  357. }
  358. } else
  359. if (disp->super & 0x00000004) {
  360. for (head = 0; head < disp->base.head.nr; head++) {
  361. if (!(mask[head] & 0x00001000))
  362. continue;
  363. nvkm_debug(subdev, "supervisor 3.0 - head %d\n", head);
  364. gf119_disp_intr_unk4_0(disp, head);
  365. }
  366. }
  367. for (head = 0; head < disp->base.head.nr; head++)
  368. nvkm_wr32(device, 0x6101d4 + (head * 0x800), 0x00000000);
  369. nvkm_wr32(device, 0x6101d0, 0x80000000);
  370. }
  371. static void
  372. gf119_disp_intr_error(struct nv50_disp *disp, int chid)
  373. {
  374. struct nvkm_subdev *subdev = &disp->base.engine.subdev;
  375. struct nvkm_device *device = subdev->device;
  376. u32 mthd = nvkm_rd32(device, 0x6101f0 + (chid * 12));
  377. u32 data = nvkm_rd32(device, 0x6101f4 + (chid * 12));
  378. u32 unkn = nvkm_rd32(device, 0x6101f8 + (chid * 12));
  379. nvkm_error(subdev, "chid %d mthd %04x data %08x %08x %08x\n",
  380. chid, (mthd & 0x0000ffc), data, mthd, unkn);
  381. if (chid < ARRAY_SIZE(disp->chan)) {
  382. switch (mthd & 0xffc) {
  383. case 0x0080:
  384. nv50_disp_chan_mthd(disp->chan[chid], NV_DBG_ERROR);
  385. break;
  386. default:
  387. break;
  388. }
  389. }
  390. nvkm_wr32(device, 0x61009c, (1 << chid));
  391. nvkm_wr32(device, 0x6101f0 + (chid * 12), 0x90000000);
  392. }
  393. void
  394. gf119_disp_intr(struct nv50_disp *disp)
  395. {
  396. struct nvkm_subdev *subdev = &disp->base.engine.subdev;
  397. struct nvkm_device *device = subdev->device;
  398. u32 intr = nvkm_rd32(device, 0x610088);
  399. int i;
  400. if (intr & 0x00000001) {
  401. u32 stat = nvkm_rd32(device, 0x61008c);
  402. while (stat) {
  403. int chid = __ffs(stat); stat &= ~(1 << chid);
  404. nv50_disp_chan_uevent_send(disp, chid);
  405. nvkm_wr32(device, 0x61008c, 1 << chid);
  406. }
  407. intr &= ~0x00000001;
  408. }
  409. if (intr & 0x00000002) {
  410. u32 stat = nvkm_rd32(device, 0x61009c);
  411. int chid = ffs(stat) - 1;
  412. if (chid >= 0)
  413. gf119_disp_intr_error(disp, chid);
  414. intr &= ~0x00000002;
  415. }
  416. if (intr & 0x00100000) {
  417. u32 stat = nvkm_rd32(device, 0x6100ac);
  418. if (stat & 0x00000007) {
  419. disp->super = (stat & 0x00000007);
  420. schedule_work(&disp->supervisor);
  421. nvkm_wr32(device, 0x6100ac, disp->super);
  422. stat &= ~0x00000007;
  423. }
  424. if (stat) {
  425. nvkm_warn(subdev, "intr24 %08x\n", stat);
  426. nvkm_wr32(device, 0x6100ac, stat);
  427. }
  428. intr &= ~0x00100000;
  429. }
  430. for (i = 0; i < disp->base.head.nr; i++) {
  431. u32 mask = 0x01000000 << i;
  432. if (mask & intr) {
  433. u32 stat = nvkm_rd32(device, 0x6100bc + (i * 0x800));
  434. if (stat & 0x00000001)
  435. nvkm_disp_vblank(&disp->base, i);
  436. nvkm_mask(device, 0x6100bc + (i * 0x800), 0, 0);
  437. nvkm_rd32(device, 0x6100c0 + (i * 0x800));
  438. }
  439. }
  440. }
  441. int
  442. gf119_disp_new_(const struct nv50_disp_func *func, struct nvkm_device *device,
  443. int index, struct nvkm_disp **pdisp)
  444. {
  445. u32 heads = nvkm_rd32(device, 0x022448);
  446. return nv50_disp_new_(func, device, index, heads, pdisp);
  447. }
  448. static const struct nv50_disp_func
  449. gf119_disp = {
  450. .intr = gf119_disp_intr,
  451. .uevent = &gf119_disp_chan_uevent,
  452. .super = gf119_disp_intr_supervisor,
  453. .root = &gf119_disp_root_oclass,
  454. .head.vblank_init = gf119_disp_vblank_init,
  455. .head.vblank_fini = gf119_disp_vblank_fini,
  456. .head.scanoutpos = gf119_disp_root_scanoutpos,
  457. .outp.internal.crt = nv50_dac_output_new,
  458. .outp.internal.tmds = nv50_sor_output_new,
  459. .outp.internal.lvds = nv50_sor_output_new,
  460. .outp.internal.dp = gf119_sor_dp_new,
  461. .dac.nr = 3,
  462. .dac.power = nv50_dac_power,
  463. .dac.sense = nv50_dac_sense,
  464. .sor.nr = 4,
  465. .sor.power = nv50_sor_power,
  466. .sor.hda_eld = gf119_hda_eld,
  467. .sor.hdmi = gf119_hdmi_ctrl,
  468. };
  469. int
  470. gf119_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
  471. {
  472. return gf119_disp_new_(&gf119_disp, device, index, pdisp);
  473. }