nvc0_pm.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. /*
  2. * Copyright 2011 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 "nouveau_drm.h"
  25. #include "nouveau_bios.h"
  26. #include "nouveau_pm.h"
  27. #include <subdev/bios/pll.h>
  28. #include <subdev/bios.h>
  29. #include <subdev/clock.h>
  30. #include <subdev/timer.h>
  31. #include <subdev/fb.h>
  32. static u32 read_div(struct drm_device *, int, u32, u32);
  33. static u32 read_pll(struct drm_device *, u32);
  34. static u32
  35. read_vco(struct drm_device *dev, u32 dsrc)
  36. {
  37. struct nouveau_device *device = nouveau_dev(dev);
  38. u32 ssrc = nv_rd32(device, dsrc);
  39. if (!(ssrc & 0x00000100))
  40. return read_pll(dev, 0x00e800);
  41. return read_pll(dev, 0x00e820);
  42. }
  43. static u32
  44. read_pll(struct drm_device *dev, u32 pll)
  45. {
  46. struct nouveau_device *device = nouveau_dev(dev);
  47. u32 ctrl = nv_rd32(device, pll + 0);
  48. u32 coef = nv_rd32(device, pll + 4);
  49. u32 P = (coef & 0x003f0000) >> 16;
  50. u32 N = (coef & 0x0000ff00) >> 8;
  51. u32 M = (coef & 0x000000ff) >> 0;
  52. u32 sclk, doff;
  53. if (!(ctrl & 0x00000001))
  54. return 0;
  55. switch (pll & 0xfff000) {
  56. case 0x00e000:
  57. sclk = 27000;
  58. P = 1;
  59. break;
  60. case 0x137000:
  61. doff = (pll - 0x137000) / 0x20;
  62. sclk = read_div(dev, doff, 0x137120, 0x137140);
  63. break;
  64. case 0x132000:
  65. switch (pll) {
  66. case 0x132000:
  67. sclk = read_pll(dev, 0x132020);
  68. break;
  69. case 0x132020:
  70. sclk = read_div(dev, 0, 0x137320, 0x137330);
  71. break;
  72. default:
  73. return 0;
  74. }
  75. break;
  76. default:
  77. return 0;
  78. }
  79. return sclk * N / M / P;
  80. }
  81. static u32
  82. read_div(struct drm_device *dev, int doff, u32 dsrc, u32 dctl)
  83. {
  84. struct nouveau_device *device = nouveau_dev(dev);
  85. u32 ssrc = nv_rd32(device, dsrc + (doff * 4));
  86. u32 sctl = nv_rd32(device, dctl + (doff * 4));
  87. switch (ssrc & 0x00000003) {
  88. case 0:
  89. if ((ssrc & 0x00030000) != 0x00030000)
  90. return 27000;
  91. return 108000;
  92. case 2:
  93. return 100000;
  94. case 3:
  95. if (sctl & 0x80000000) {
  96. u32 sclk = read_vco(dev, dsrc + (doff * 4));
  97. u32 sdiv = (sctl & 0x0000003f) + 2;
  98. return (sclk * 2) / sdiv;
  99. }
  100. return read_vco(dev, dsrc + (doff * 4));
  101. default:
  102. return 0;
  103. }
  104. }
  105. static u32
  106. read_mem(struct drm_device *dev)
  107. {
  108. struct nouveau_device *device = nouveau_dev(dev);
  109. u32 ssel = nv_rd32(device, 0x1373f0);
  110. if (ssel & 0x00000001)
  111. return read_div(dev, 0, 0x137300, 0x137310);
  112. return read_pll(dev, 0x132000);
  113. }
  114. static u32
  115. read_clk(struct drm_device *dev, int clk)
  116. {
  117. struct nouveau_device *device = nouveau_dev(dev);
  118. u32 sctl = nv_rd32(device, 0x137250 + (clk * 4));
  119. u32 ssel = nv_rd32(device, 0x137100);
  120. u32 sclk, sdiv;
  121. if (ssel & (1 << clk)) {
  122. if (clk < 7)
  123. sclk = read_pll(dev, 0x137000 + (clk * 0x20));
  124. else
  125. sclk = read_pll(dev, 0x1370e0);
  126. sdiv = ((sctl & 0x00003f00) >> 8) + 2;
  127. } else {
  128. sclk = read_div(dev, clk, 0x137160, 0x1371d0);
  129. sdiv = ((sctl & 0x0000003f) >> 0) + 2;
  130. }
  131. if (sctl & 0x80000000)
  132. return (sclk * 2) / sdiv;
  133. return sclk;
  134. }
  135. int
  136. nvc0_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
  137. {
  138. perflvl->shader = read_clk(dev, 0x00);
  139. perflvl->core = perflvl->shader / 2;
  140. perflvl->memory = read_mem(dev);
  141. perflvl->rop = read_clk(dev, 0x01);
  142. perflvl->hub07 = read_clk(dev, 0x02);
  143. perflvl->hub06 = read_clk(dev, 0x07);
  144. perflvl->hub01 = read_clk(dev, 0x08);
  145. perflvl->copy = read_clk(dev, 0x09);
  146. perflvl->daemon = read_clk(dev, 0x0c);
  147. perflvl->vdec = read_clk(dev, 0x0e);
  148. return 0;
  149. }
  150. struct nvc0_pm_clock {
  151. u32 freq;
  152. u32 ssel;
  153. u32 mdiv;
  154. u32 dsrc;
  155. u32 ddiv;
  156. u32 coef;
  157. };
  158. struct nvc0_pm_state {
  159. struct nouveau_pm_level *perflvl;
  160. struct nvc0_pm_clock eng[16];
  161. struct nvc0_pm_clock mem;
  162. };
  163. static u32
  164. calc_div(struct drm_device *dev, int clk, u32 ref, u32 freq, u32 *ddiv)
  165. {
  166. u32 div = min((ref * 2) / freq, (u32)65);
  167. if (div < 2)
  168. div = 2;
  169. *ddiv = div - 2;
  170. return (ref * 2) / div;
  171. }
  172. static u32
  173. calc_src(struct drm_device *dev, int clk, u32 freq, u32 *dsrc, u32 *ddiv)
  174. {
  175. u32 sclk;
  176. /* use one of the fixed frequencies if possible */
  177. *ddiv = 0x00000000;
  178. switch (freq) {
  179. case 27000:
  180. case 108000:
  181. *dsrc = 0x00000000;
  182. if (freq == 108000)
  183. *dsrc |= 0x00030000;
  184. return freq;
  185. case 100000:
  186. *dsrc = 0x00000002;
  187. return freq;
  188. default:
  189. *dsrc = 0x00000003;
  190. break;
  191. }
  192. /* otherwise, calculate the closest divider */
  193. sclk = read_vco(dev, clk);
  194. if (clk < 7)
  195. sclk = calc_div(dev, clk, sclk, freq, ddiv);
  196. return sclk;
  197. }
  198. static u32
  199. calc_pll(struct drm_device *dev, int clk, u32 freq, u32 *coef)
  200. {
  201. struct nouveau_device *device = nouveau_dev(dev);
  202. struct nouveau_bios *bios = nouveau_bios(device);
  203. struct nvbios_pll limits;
  204. int N, M, P, ret;
  205. ret = nvbios_pll_parse(bios, 0x137000 + (clk * 0x20), &limits);
  206. if (ret)
  207. return 0;
  208. limits.refclk = read_div(dev, clk, 0x137120, 0x137140);
  209. if (!limits.refclk)
  210. return 0;
  211. ret = nva3_calc_pll(dev, &limits, freq, &N, NULL, &M, &P);
  212. if (ret <= 0)
  213. return 0;
  214. *coef = (P << 16) | (N << 8) | M;
  215. return ret;
  216. }
  217. /* A (likely rather simplified and incomplete) view of the clock tree
  218. *
  219. * Key:
  220. *
  221. * S: source select
  222. * D: divider
  223. * P: pll
  224. * F: switch
  225. *
  226. * Engine clocks:
  227. *
  228. * 137250(D) ---- 137100(F0) ---- 137160(S)/1371d0(D) ------------------- ref
  229. * (F1) ---- 1370X0(P) ---- 137120(S)/137140(D) ---- ref
  230. *
  231. * Not all registers exist for all clocks. For example: clocks >= 8 don't
  232. * have their own PLL (all tied to clock 7's PLL when in PLL mode), nor do
  233. * they have the divider at 1371d0, though the source selection at 137160
  234. * still exists. You must use the divider at 137250 for these instead.
  235. *
  236. * Memory clock:
  237. *
  238. * TBD, read_mem() above is likely very wrong...
  239. *
  240. */
  241. static int
  242. calc_clk(struct drm_device *dev, int clk, struct nvc0_pm_clock *info, u32 freq)
  243. {
  244. u32 src0, div0, div1D, div1P = 0;
  245. u32 clk0, clk1 = 0;
  246. /* invalid clock domain */
  247. if (!freq)
  248. return 0;
  249. /* first possible path, using only dividers */
  250. clk0 = calc_src(dev, clk, freq, &src0, &div0);
  251. clk0 = calc_div(dev, clk, clk0, freq, &div1D);
  252. /* see if we can get any closer using PLLs */
  253. if (clk0 != freq && (0x00004387 & (1 << clk))) {
  254. if (clk < 7)
  255. clk1 = calc_pll(dev, clk, freq, &info->coef);
  256. else
  257. clk1 = read_pll(dev, 0x1370e0);
  258. clk1 = calc_div(dev, clk, clk1, freq, &div1P);
  259. }
  260. /* select the method which gets closest to target freq */
  261. if (abs((int)freq - clk0) <= abs((int)freq - clk1)) {
  262. info->dsrc = src0;
  263. if (div0) {
  264. info->ddiv |= 0x80000000;
  265. info->ddiv |= div0 << 8;
  266. info->ddiv |= div0;
  267. }
  268. if (div1D) {
  269. info->mdiv |= 0x80000000;
  270. info->mdiv |= div1D;
  271. }
  272. info->ssel = 0;
  273. info->freq = clk0;
  274. } else {
  275. if (div1P) {
  276. info->mdiv |= 0x80000000;
  277. info->mdiv |= div1P << 8;
  278. }
  279. info->ssel = (1 << clk);
  280. info->freq = clk1;
  281. }
  282. return 0;
  283. }
  284. static int
  285. calc_mem(struct drm_device *dev, struct nvc0_pm_clock *info, u32 freq)
  286. {
  287. struct nouveau_device *device = nouveau_dev(dev);
  288. struct nouveau_bios *bios = nouveau_bios(device);
  289. struct nvbios_pll pll;
  290. int N, M, P, ret;
  291. u32 ctrl;
  292. /* mclk pll input freq comes from another pll, make sure it's on */
  293. ctrl = nv_rd32(device, 0x132020);
  294. if (!(ctrl & 0x00000001)) {
  295. /* if not, program it to 567MHz. nfi where this value comes
  296. * from - it looks like it's in the pll limits table for
  297. * 132000 but the binary driver ignores all my attempts to
  298. * change this value.
  299. */
  300. nv_wr32(device, 0x137320, 0x00000103);
  301. nv_wr32(device, 0x137330, 0x81200606);
  302. nv_wait(device, 0x132020, 0x00010000, 0x00010000);
  303. nv_wr32(device, 0x132024, 0x0001150f);
  304. nv_mask(device, 0x132020, 0x00000001, 0x00000001);
  305. nv_wait(device, 0x137390, 0x00020000, 0x00020000);
  306. nv_mask(device, 0x132020, 0x00000004, 0x00000004);
  307. }
  308. /* for the moment, until the clock tree is better understood, use
  309. * pll mode for all clock frequencies
  310. */
  311. ret = nvbios_pll_parse(bios, 0x132000, &pll);
  312. if (ret == 0) {
  313. pll.refclk = read_pll(dev, 0x132020);
  314. if (pll.refclk) {
  315. ret = nva3_calc_pll(dev, &pll, freq, &N, NULL, &M, &P);
  316. if (ret > 0) {
  317. info->coef = (P << 16) | (N << 8) | M;
  318. return 0;
  319. }
  320. }
  321. }
  322. return -EINVAL;
  323. }
  324. void *
  325. nvc0_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
  326. {
  327. struct nouveau_device *device = nouveau_dev(dev);
  328. struct nvc0_pm_state *info;
  329. int ret;
  330. info = kzalloc(sizeof(*info), GFP_KERNEL);
  331. if (!info)
  332. return ERR_PTR(-ENOMEM);
  333. /* NFI why this is still in the performance table, the ROPCs appear
  334. * to get their clock from clock 2 ("hub07", actually hub05 on this
  335. * chip, but, anyway...) as well. nvatiming confirms hub05 and ROP
  336. * are always the same freq with the binary driver even when the
  337. * performance table says they should differ.
  338. */
  339. if (device->chipset == 0xd9)
  340. perflvl->rop = 0;
  341. if ((ret = calc_clk(dev, 0x00, &info->eng[0x00], perflvl->shader)) ||
  342. (ret = calc_clk(dev, 0x01, &info->eng[0x01], perflvl->rop)) ||
  343. (ret = calc_clk(dev, 0x02, &info->eng[0x02], perflvl->hub07)) ||
  344. (ret = calc_clk(dev, 0x07, &info->eng[0x07], perflvl->hub06)) ||
  345. (ret = calc_clk(dev, 0x08, &info->eng[0x08], perflvl->hub01)) ||
  346. (ret = calc_clk(dev, 0x09, &info->eng[0x09], perflvl->copy)) ||
  347. (ret = calc_clk(dev, 0x0c, &info->eng[0x0c], perflvl->daemon)) ||
  348. (ret = calc_clk(dev, 0x0e, &info->eng[0x0e], perflvl->vdec))) {
  349. kfree(info);
  350. return ERR_PTR(ret);
  351. }
  352. if (perflvl->memory) {
  353. ret = calc_mem(dev, &info->mem, perflvl->memory);
  354. if (ret) {
  355. kfree(info);
  356. return ERR_PTR(ret);
  357. }
  358. }
  359. info->perflvl = perflvl;
  360. return info;
  361. }
  362. static void
  363. prog_clk(struct drm_device *dev, int clk, struct nvc0_pm_clock *info)
  364. {
  365. struct nouveau_device *device = nouveau_dev(dev);
  366. /* program dividers at 137160/1371d0 first */
  367. if (clk < 7 && !info->ssel) {
  368. nv_mask(device, 0x1371d0 + (clk * 0x04), 0x80003f3f, info->ddiv);
  369. nv_wr32(device, 0x137160 + (clk * 0x04), info->dsrc);
  370. }
  371. /* switch clock to non-pll mode */
  372. nv_mask(device, 0x137100, (1 << clk), 0x00000000);
  373. nv_wait(device, 0x137100, (1 << clk), 0x00000000);
  374. /* reprogram pll */
  375. if (clk < 7) {
  376. /* make sure it's disabled first... */
  377. u32 base = 0x137000 + (clk * 0x20);
  378. u32 ctrl = nv_rd32(device, base + 0x00);
  379. if (ctrl & 0x00000001) {
  380. nv_mask(device, base + 0x00, 0x00000004, 0x00000000);
  381. nv_mask(device, base + 0x00, 0x00000001, 0x00000000);
  382. }
  383. /* program it to new values, if necessary */
  384. if (info->ssel) {
  385. nv_wr32(device, base + 0x04, info->coef);
  386. nv_mask(device, base + 0x00, 0x00000001, 0x00000001);
  387. nv_wait(device, base + 0x00, 0x00020000, 0x00020000);
  388. nv_mask(device, base + 0x00, 0x00020004, 0x00000004);
  389. }
  390. }
  391. /* select pll/non-pll mode, and program final clock divider */
  392. nv_mask(device, 0x137100, (1 << clk), info->ssel);
  393. nv_wait(device, 0x137100, (1 << clk), info->ssel);
  394. nv_mask(device, 0x137250 + (clk * 0x04), 0x00003f3f, info->mdiv);
  395. }
  396. static void
  397. mclk_precharge(struct nouveau_mem_exec_func *exec)
  398. {
  399. }
  400. static void
  401. mclk_refresh(struct nouveau_mem_exec_func *exec)
  402. {
  403. }
  404. static void
  405. mclk_refresh_auto(struct nouveau_mem_exec_func *exec, bool enable)
  406. {
  407. struct nouveau_device *device = nouveau_dev(exec->dev);
  408. nv_wr32(device, 0x10f210, enable ? 0x80000000 : 0x00000000);
  409. }
  410. static void
  411. mclk_refresh_self(struct nouveau_mem_exec_func *exec, bool enable)
  412. {
  413. }
  414. static void
  415. mclk_wait(struct nouveau_mem_exec_func *exec, u32 nsec)
  416. {
  417. udelay((nsec + 500) / 1000);
  418. }
  419. static u32
  420. mclk_mrg(struct nouveau_mem_exec_func *exec, int mr)
  421. {
  422. struct nouveau_device *device = nouveau_dev(exec->dev);
  423. struct nouveau_fb *pfb = nouveau_fb(device);
  424. if (pfb->ram.type != NV_MEM_TYPE_GDDR5) {
  425. if (mr <= 1)
  426. return nv_rd32(device, 0x10f300 + ((mr - 0) * 4));
  427. return nv_rd32(device, 0x10f320 + ((mr - 2) * 4));
  428. } else {
  429. if (mr == 0)
  430. return nv_rd32(device, 0x10f300 + (mr * 4));
  431. else
  432. if (mr <= 7)
  433. return nv_rd32(device, 0x10f32c + (mr * 4));
  434. return nv_rd32(device, 0x10f34c);
  435. }
  436. }
  437. static void
  438. mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data)
  439. {
  440. struct nouveau_device *device = nouveau_dev(exec->dev);
  441. struct nouveau_fb *pfb = nouveau_fb(device);
  442. if (pfb->ram.type != NV_MEM_TYPE_GDDR5) {
  443. if (mr <= 1) {
  444. nv_wr32(device, 0x10f300 + ((mr - 0) * 4), data);
  445. if (pfb->ram.ranks > 1)
  446. nv_wr32(device, 0x10f308 + ((mr - 0) * 4), data);
  447. } else
  448. if (mr <= 3) {
  449. nv_wr32(device, 0x10f320 + ((mr - 2) * 4), data);
  450. if (pfb->ram.ranks > 1)
  451. nv_wr32(device, 0x10f328 + ((mr - 2) * 4), data);
  452. }
  453. } else {
  454. if (mr == 0) nv_wr32(device, 0x10f300 + (mr * 4), data);
  455. else if (mr <= 7) nv_wr32(device, 0x10f32c + (mr * 4), data);
  456. else if (mr == 15) nv_wr32(device, 0x10f34c, data);
  457. }
  458. }
  459. static void
  460. mclk_clock_set(struct nouveau_mem_exec_func *exec)
  461. {
  462. struct nouveau_device *device = nouveau_dev(exec->dev);
  463. struct nvc0_pm_state *info = exec->priv;
  464. u32 ctrl = nv_rd32(device, 0x132000);
  465. nv_wr32(device, 0x137360, 0x00000001);
  466. nv_wr32(device, 0x137370, 0x00000000);
  467. nv_wr32(device, 0x137380, 0x00000000);
  468. if (ctrl & 0x00000001)
  469. nv_wr32(device, 0x132000, (ctrl &= ~0x00000001));
  470. nv_wr32(device, 0x132004, info->mem.coef);
  471. nv_wr32(device, 0x132000, (ctrl |= 0x00000001));
  472. nv_wait(device, 0x137390, 0x00000002, 0x00000002);
  473. nv_wr32(device, 0x132018, 0x00005000);
  474. nv_wr32(device, 0x137370, 0x00000001);
  475. nv_wr32(device, 0x137380, 0x00000001);
  476. nv_wr32(device, 0x137360, 0x00000000);
  477. }
  478. static void
  479. mclk_timing_set(struct nouveau_mem_exec_func *exec)
  480. {
  481. struct nouveau_device *device = nouveau_dev(exec->dev);
  482. struct nvc0_pm_state *info = exec->priv;
  483. struct nouveau_pm_level *perflvl = info->perflvl;
  484. int i;
  485. for (i = 0; i < 5; i++)
  486. nv_wr32(device, 0x10f290 + (i * 4), perflvl->timing.reg[i]);
  487. }
  488. static void
  489. prog_mem(struct drm_device *dev, struct nvc0_pm_state *info)
  490. {
  491. struct nouveau_device *device = nouveau_dev(dev);
  492. struct nouveau_mem_exec_func exec = {
  493. .dev = dev,
  494. .precharge = mclk_precharge,
  495. .refresh = mclk_refresh,
  496. .refresh_auto = mclk_refresh_auto,
  497. .refresh_self = mclk_refresh_self,
  498. .wait = mclk_wait,
  499. .mrg = mclk_mrg,
  500. .mrs = mclk_mrs,
  501. .clock_set = mclk_clock_set,
  502. .timing_set = mclk_timing_set,
  503. .priv = info
  504. };
  505. if (device->chipset < 0xd0)
  506. nv_wr32(device, 0x611200, 0x00003300);
  507. else
  508. nv_wr32(device, 0x62c000, 0x03030000);
  509. nouveau_mem_exec(&exec, info->perflvl);
  510. if (device->chipset < 0xd0)
  511. nv_wr32(device, 0x611200, 0x00003330);
  512. else
  513. nv_wr32(device, 0x62c000, 0x03030300);
  514. }
  515. int
  516. nvc0_pm_clocks_set(struct drm_device *dev, void *data)
  517. {
  518. struct nvc0_pm_state *info = data;
  519. int i;
  520. if (info->mem.coef)
  521. prog_mem(dev, info);
  522. for (i = 0; i < 16; i++) {
  523. if (!info->eng[i].freq)
  524. continue;
  525. prog_clk(dev, i, &info->eng[i]);
  526. }
  527. kfree(info);
  528. return 0;
  529. }