helpers.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236
  1. /*
  2. * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
  3. * Copyright (C) 2017 Linaro Ltd.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 and
  7. * only version 2 as published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. */
  15. #include <linux/clk.h>
  16. #include <linux/iopoll.h>
  17. #include <linux/list.h>
  18. #include <linux/mutex.h>
  19. #include <linux/pm_runtime.h>
  20. #include <linux/slab.h>
  21. #include <media/videobuf2-dma-sg.h>
  22. #include <media/v4l2-mem2mem.h>
  23. #include <asm/div64.h>
  24. #include "core.h"
  25. #include "helpers.h"
  26. #include "hfi_helper.h"
  27. #include "hfi_venus_io.h"
  28. struct intbuf {
  29. struct list_head list;
  30. u32 type;
  31. size_t size;
  32. void *va;
  33. dma_addr_t da;
  34. unsigned long attrs;
  35. };
  36. bool venus_helper_check_codec(struct venus_inst *inst, u32 v4l2_pixfmt)
  37. {
  38. struct venus_core *core = inst->core;
  39. u32 session_type = inst->session_type;
  40. u32 codec;
  41. switch (v4l2_pixfmt) {
  42. case V4L2_PIX_FMT_H264:
  43. codec = HFI_VIDEO_CODEC_H264;
  44. break;
  45. case V4L2_PIX_FMT_H263:
  46. codec = HFI_VIDEO_CODEC_H263;
  47. break;
  48. case V4L2_PIX_FMT_MPEG1:
  49. codec = HFI_VIDEO_CODEC_MPEG1;
  50. break;
  51. case V4L2_PIX_FMT_MPEG2:
  52. codec = HFI_VIDEO_CODEC_MPEG2;
  53. break;
  54. case V4L2_PIX_FMT_MPEG4:
  55. codec = HFI_VIDEO_CODEC_MPEG4;
  56. break;
  57. case V4L2_PIX_FMT_VC1_ANNEX_G:
  58. case V4L2_PIX_FMT_VC1_ANNEX_L:
  59. codec = HFI_VIDEO_CODEC_VC1;
  60. break;
  61. case V4L2_PIX_FMT_VP8:
  62. codec = HFI_VIDEO_CODEC_VP8;
  63. break;
  64. case V4L2_PIX_FMT_VP9:
  65. codec = HFI_VIDEO_CODEC_VP9;
  66. break;
  67. case V4L2_PIX_FMT_XVID:
  68. codec = HFI_VIDEO_CODEC_DIVX;
  69. break;
  70. case V4L2_PIX_FMT_HEVC:
  71. codec = HFI_VIDEO_CODEC_HEVC;
  72. break;
  73. default:
  74. return false;
  75. }
  76. if (session_type == VIDC_SESSION_TYPE_ENC && core->enc_codecs & codec)
  77. return true;
  78. if (session_type == VIDC_SESSION_TYPE_DEC && core->dec_codecs & codec)
  79. return true;
  80. return false;
  81. }
  82. EXPORT_SYMBOL_GPL(venus_helper_check_codec);
  83. static int venus_helper_queue_dpb_bufs(struct venus_inst *inst)
  84. {
  85. struct intbuf *buf;
  86. int ret = 0;
  87. list_for_each_entry(buf, &inst->dpbbufs, list) {
  88. struct hfi_frame_data fdata;
  89. memset(&fdata, 0, sizeof(fdata));
  90. fdata.alloc_len = buf->size;
  91. fdata.device_addr = buf->da;
  92. fdata.buffer_type = buf->type;
  93. ret = hfi_session_process_buf(inst, &fdata);
  94. if (ret)
  95. goto fail;
  96. }
  97. fail:
  98. return ret;
  99. }
  100. int venus_helper_free_dpb_bufs(struct venus_inst *inst)
  101. {
  102. struct intbuf *buf, *n;
  103. list_for_each_entry_safe(buf, n, &inst->dpbbufs, list) {
  104. list_del_init(&buf->list);
  105. dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da,
  106. buf->attrs);
  107. kfree(buf);
  108. }
  109. INIT_LIST_HEAD(&inst->dpbbufs);
  110. return 0;
  111. }
  112. EXPORT_SYMBOL_GPL(venus_helper_free_dpb_bufs);
  113. int venus_helper_alloc_dpb_bufs(struct venus_inst *inst)
  114. {
  115. struct venus_core *core = inst->core;
  116. struct device *dev = core->dev;
  117. enum hfi_version ver = core->res->hfi_version;
  118. struct hfi_buffer_requirements bufreq;
  119. u32 buftype = inst->dpb_buftype;
  120. unsigned int dpb_size = 0;
  121. struct intbuf *buf;
  122. unsigned int i;
  123. u32 count;
  124. int ret;
  125. /* no need to allocate dpb buffers */
  126. if (!inst->dpb_fmt)
  127. return 0;
  128. if (inst->dpb_buftype == HFI_BUFFER_OUTPUT)
  129. dpb_size = inst->output_buf_size;
  130. else if (inst->dpb_buftype == HFI_BUFFER_OUTPUT2)
  131. dpb_size = inst->output2_buf_size;
  132. if (!dpb_size)
  133. return 0;
  134. ret = venus_helper_get_bufreq(inst, buftype, &bufreq);
  135. if (ret)
  136. return ret;
  137. count = HFI_BUFREQ_COUNT_MIN(&bufreq, ver);
  138. for (i = 0; i < count; i++) {
  139. buf = kzalloc(sizeof(*buf), GFP_KERNEL);
  140. if (!buf) {
  141. ret = -ENOMEM;
  142. goto fail;
  143. }
  144. buf->type = buftype;
  145. buf->size = dpb_size;
  146. buf->attrs = DMA_ATTR_WRITE_COMBINE |
  147. DMA_ATTR_NO_KERNEL_MAPPING;
  148. buf->va = dma_alloc_attrs(dev, buf->size, &buf->da, GFP_KERNEL,
  149. buf->attrs);
  150. if (!buf->va) {
  151. kfree(buf);
  152. ret = -ENOMEM;
  153. goto fail;
  154. }
  155. list_add_tail(&buf->list, &inst->dpbbufs);
  156. }
  157. return 0;
  158. fail:
  159. venus_helper_free_dpb_bufs(inst);
  160. return ret;
  161. }
  162. EXPORT_SYMBOL_GPL(venus_helper_alloc_dpb_bufs);
  163. static int intbufs_set_buffer(struct venus_inst *inst, u32 type)
  164. {
  165. struct venus_core *core = inst->core;
  166. struct device *dev = core->dev;
  167. struct hfi_buffer_requirements bufreq;
  168. struct hfi_buffer_desc bd;
  169. struct intbuf *buf;
  170. unsigned int i;
  171. int ret;
  172. ret = venus_helper_get_bufreq(inst, type, &bufreq);
  173. if (ret)
  174. return 0;
  175. if (!bufreq.size)
  176. return 0;
  177. for (i = 0; i < bufreq.count_actual; i++) {
  178. buf = kzalloc(sizeof(*buf), GFP_KERNEL);
  179. if (!buf) {
  180. ret = -ENOMEM;
  181. goto fail;
  182. }
  183. buf->type = bufreq.type;
  184. buf->size = bufreq.size;
  185. buf->attrs = DMA_ATTR_WRITE_COMBINE |
  186. DMA_ATTR_NO_KERNEL_MAPPING;
  187. buf->va = dma_alloc_attrs(dev, buf->size, &buf->da, GFP_KERNEL,
  188. buf->attrs);
  189. if (!buf->va) {
  190. ret = -ENOMEM;
  191. goto fail;
  192. }
  193. memset(&bd, 0, sizeof(bd));
  194. bd.buffer_size = buf->size;
  195. bd.buffer_type = buf->type;
  196. bd.num_buffers = 1;
  197. bd.device_addr = buf->da;
  198. ret = hfi_session_set_buffers(inst, &bd);
  199. if (ret) {
  200. dev_err(dev, "set session buffers failed\n");
  201. goto dma_free;
  202. }
  203. list_add_tail(&buf->list, &inst->internalbufs);
  204. }
  205. return 0;
  206. dma_free:
  207. dma_free_attrs(dev, buf->size, buf->va, buf->da, buf->attrs);
  208. fail:
  209. kfree(buf);
  210. return ret;
  211. }
  212. static int intbufs_unset_buffers(struct venus_inst *inst)
  213. {
  214. struct hfi_buffer_desc bd = {0};
  215. struct intbuf *buf, *n;
  216. int ret = 0;
  217. list_for_each_entry_safe(buf, n, &inst->internalbufs, list) {
  218. bd.buffer_size = buf->size;
  219. bd.buffer_type = buf->type;
  220. bd.num_buffers = 1;
  221. bd.device_addr = buf->da;
  222. bd.response_required = true;
  223. ret = hfi_session_unset_buffers(inst, &bd);
  224. list_del_init(&buf->list);
  225. dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da,
  226. buf->attrs);
  227. kfree(buf);
  228. }
  229. return ret;
  230. }
  231. static const unsigned int intbuf_types_1xx[] = {
  232. HFI_BUFFER_INTERNAL_SCRATCH(HFI_VERSION_1XX),
  233. HFI_BUFFER_INTERNAL_SCRATCH_1(HFI_VERSION_1XX),
  234. HFI_BUFFER_INTERNAL_SCRATCH_2(HFI_VERSION_1XX),
  235. HFI_BUFFER_INTERNAL_PERSIST,
  236. HFI_BUFFER_INTERNAL_PERSIST_1,
  237. };
  238. static const unsigned int intbuf_types_4xx[] = {
  239. HFI_BUFFER_INTERNAL_SCRATCH(HFI_VERSION_4XX),
  240. HFI_BUFFER_INTERNAL_SCRATCH_1(HFI_VERSION_4XX),
  241. HFI_BUFFER_INTERNAL_SCRATCH_2(HFI_VERSION_4XX),
  242. HFI_BUFFER_INTERNAL_PERSIST,
  243. HFI_BUFFER_INTERNAL_PERSIST_1,
  244. };
  245. static int intbufs_alloc(struct venus_inst *inst)
  246. {
  247. const unsigned int *intbuf;
  248. size_t arr_sz, i;
  249. int ret;
  250. if (IS_V4(inst->core)) {
  251. arr_sz = ARRAY_SIZE(intbuf_types_4xx);
  252. intbuf = intbuf_types_4xx;
  253. } else {
  254. arr_sz = ARRAY_SIZE(intbuf_types_1xx);
  255. intbuf = intbuf_types_1xx;
  256. }
  257. for (i = 0; i < arr_sz; i++) {
  258. ret = intbufs_set_buffer(inst, intbuf[i]);
  259. if (ret)
  260. goto error;
  261. }
  262. return 0;
  263. error:
  264. intbufs_unset_buffers(inst);
  265. return ret;
  266. }
  267. static int intbufs_free(struct venus_inst *inst)
  268. {
  269. return intbufs_unset_buffers(inst);
  270. }
  271. static u32 load_per_instance(struct venus_inst *inst)
  272. {
  273. u32 mbs;
  274. if (!inst || !(inst->state >= INST_INIT && inst->state < INST_STOP))
  275. return 0;
  276. mbs = (ALIGN(inst->width, 16) / 16) * (ALIGN(inst->height, 16) / 16);
  277. return mbs * inst->fps;
  278. }
  279. static u32 load_per_type(struct venus_core *core, u32 session_type)
  280. {
  281. struct venus_inst *inst = NULL;
  282. u32 mbs_per_sec = 0;
  283. mutex_lock(&core->lock);
  284. list_for_each_entry(inst, &core->instances, list) {
  285. if (inst->session_type != session_type)
  286. continue;
  287. mbs_per_sec += load_per_instance(inst);
  288. }
  289. mutex_unlock(&core->lock);
  290. return mbs_per_sec;
  291. }
  292. static int load_scale_clocks(struct venus_core *core)
  293. {
  294. const struct freq_tbl *table = core->res->freq_tbl;
  295. unsigned int num_rows = core->res->freq_tbl_size;
  296. unsigned long freq = table[0].freq;
  297. struct clk *clk = core->clks[0];
  298. struct device *dev = core->dev;
  299. u32 mbs_per_sec;
  300. unsigned int i;
  301. int ret;
  302. mbs_per_sec = load_per_type(core, VIDC_SESSION_TYPE_ENC) +
  303. load_per_type(core, VIDC_SESSION_TYPE_DEC);
  304. if (mbs_per_sec > core->res->max_load)
  305. dev_warn(dev, "HW is overloaded, needed: %d max: %d\n",
  306. mbs_per_sec, core->res->max_load);
  307. if (!mbs_per_sec && num_rows > 1) {
  308. freq = table[num_rows - 1].freq;
  309. goto set_freq;
  310. }
  311. for (i = 0; i < num_rows; i++) {
  312. if (mbs_per_sec > table[i].load)
  313. break;
  314. freq = table[i].freq;
  315. }
  316. set_freq:
  317. ret = clk_set_rate(clk, freq);
  318. if (ret)
  319. goto err;
  320. ret = clk_set_rate(core->core0_clk, freq);
  321. if (ret)
  322. goto err;
  323. ret = clk_set_rate(core->core1_clk, freq);
  324. if (ret)
  325. goto err;
  326. return 0;
  327. err:
  328. dev_err(dev, "failed to set clock rate %lu (%d)\n", freq, ret);
  329. return ret;
  330. }
  331. static void fill_buffer_desc(const struct venus_buffer *buf,
  332. struct hfi_buffer_desc *bd, bool response)
  333. {
  334. memset(bd, 0, sizeof(*bd));
  335. bd->buffer_type = HFI_BUFFER_OUTPUT;
  336. bd->buffer_size = buf->size;
  337. bd->num_buffers = 1;
  338. bd->device_addr = buf->dma_addr;
  339. bd->response_required = response;
  340. }
  341. static void return_buf_error(struct venus_inst *inst,
  342. struct vb2_v4l2_buffer *vbuf)
  343. {
  344. struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
  345. if (vbuf->vb2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
  346. v4l2_m2m_src_buf_remove_by_buf(m2m_ctx, vbuf);
  347. else
  348. v4l2_m2m_dst_buf_remove_by_buf(m2m_ctx, vbuf);
  349. v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
  350. }
  351. static int
  352. session_process_buf(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf)
  353. {
  354. struct venus_buffer *buf = to_venus_buffer(vbuf);
  355. struct vb2_buffer *vb = &vbuf->vb2_buf;
  356. unsigned int type = vb->type;
  357. struct hfi_frame_data fdata;
  358. int ret;
  359. memset(&fdata, 0, sizeof(fdata));
  360. fdata.alloc_len = buf->size;
  361. fdata.device_addr = buf->dma_addr;
  362. fdata.timestamp = vb->timestamp;
  363. do_div(fdata.timestamp, NSEC_PER_USEC);
  364. fdata.flags = 0;
  365. fdata.clnt_data = vbuf->vb2_buf.index;
  366. if (!fdata.timestamp)
  367. fdata.flags |= HFI_BUFFERFLAG_TIMESTAMPINVALID;
  368. if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
  369. fdata.buffer_type = HFI_BUFFER_INPUT;
  370. fdata.filled_len = vb2_get_plane_payload(vb, 0);
  371. fdata.offset = vb->planes[0].data_offset;
  372. if (vbuf->flags & V4L2_BUF_FLAG_LAST || !fdata.filled_len)
  373. fdata.flags |= HFI_BUFFERFLAG_EOS;
  374. } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
  375. if (inst->session_type == VIDC_SESSION_TYPE_ENC)
  376. fdata.buffer_type = HFI_BUFFER_OUTPUT;
  377. else
  378. fdata.buffer_type = inst->opb_buftype;
  379. fdata.filled_len = 0;
  380. fdata.offset = 0;
  381. }
  382. ret = hfi_session_process_buf(inst, &fdata);
  383. if (ret)
  384. return ret;
  385. return 0;
  386. }
  387. static bool is_dynamic_bufmode(struct venus_inst *inst)
  388. {
  389. struct venus_core *core = inst->core;
  390. struct venus_caps *caps;
  391. caps = venus_caps_by_codec(core, inst->hfi_codec, inst->session_type);
  392. if (!caps)
  393. return 0;
  394. return caps->cap_bufs_mode_dynamic;
  395. }
  396. static int session_unregister_bufs(struct venus_inst *inst)
  397. {
  398. struct venus_buffer *buf, *n;
  399. struct hfi_buffer_desc bd;
  400. int ret = 0;
  401. if (is_dynamic_bufmode(inst))
  402. return 0;
  403. list_for_each_entry_safe(buf, n, &inst->registeredbufs, reg_list) {
  404. fill_buffer_desc(buf, &bd, true);
  405. ret = hfi_session_unset_buffers(inst, &bd);
  406. list_del_init(&buf->reg_list);
  407. }
  408. return ret;
  409. }
  410. static int session_register_bufs(struct venus_inst *inst)
  411. {
  412. struct venus_core *core = inst->core;
  413. struct device *dev = core->dev;
  414. struct hfi_buffer_desc bd;
  415. struct venus_buffer *buf;
  416. int ret = 0;
  417. if (is_dynamic_bufmode(inst))
  418. return 0;
  419. list_for_each_entry(buf, &inst->registeredbufs, reg_list) {
  420. fill_buffer_desc(buf, &bd, false);
  421. ret = hfi_session_set_buffers(inst, &bd);
  422. if (ret) {
  423. dev_err(dev, "%s: set buffer failed\n", __func__);
  424. break;
  425. }
  426. }
  427. return ret;
  428. }
  429. static u32 to_hfi_raw_fmt(u32 v4l2_fmt)
  430. {
  431. switch (v4l2_fmt) {
  432. case V4L2_PIX_FMT_NV12:
  433. return HFI_COLOR_FORMAT_NV12;
  434. case V4L2_PIX_FMT_NV21:
  435. return HFI_COLOR_FORMAT_NV21;
  436. default:
  437. break;
  438. }
  439. return 0;
  440. }
  441. int venus_helper_get_bufreq(struct venus_inst *inst, u32 type,
  442. struct hfi_buffer_requirements *req)
  443. {
  444. u32 ptype = HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS;
  445. union hfi_get_property hprop;
  446. unsigned int i;
  447. int ret;
  448. if (req)
  449. memset(req, 0, sizeof(*req));
  450. ret = hfi_session_get_property(inst, ptype, &hprop);
  451. if (ret)
  452. return ret;
  453. ret = -EINVAL;
  454. for (i = 0; i < HFI_BUFFER_TYPE_MAX; i++) {
  455. if (hprop.bufreq[i].type != type)
  456. continue;
  457. if (req)
  458. memcpy(req, &hprop.bufreq[i], sizeof(*req));
  459. ret = 0;
  460. break;
  461. }
  462. return ret;
  463. }
  464. EXPORT_SYMBOL_GPL(venus_helper_get_bufreq);
  465. static u32 get_framesize_raw_nv12(u32 width, u32 height)
  466. {
  467. u32 y_stride, uv_stride, y_plane;
  468. u32 y_sclines, uv_sclines, uv_plane;
  469. u32 size;
  470. y_stride = ALIGN(width, 128);
  471. uv_stride = ALIGN(width, 128);
  472. y_sclines = ALIGN(height, 32);
  473. uv_sclines = ALIGN(((height + 1) >> 1), 16);
  474. y_plane = y_stride * y_sclines;
  475. uv_plane = uv_stride * uv_sclines + SZ_4K;
  476. size = y_plane + uv_plane + SZ_8K;
  477. return ALIGN(size, SZ_4K);
  478. }
  479. static u32 get_framesize_raw_nv12_ubwc(u32 width, u32 height)
  480. {
  481. u32 y_meta_stride, y_meta_plane;
  482. u32 y_stride, y_plane;
  483. u32 uv_meta_stride, uv_meta_plane;
  484. u32 uv_stride, uv_plane;
  485. u32 extradata = SZ_16K;
  486. y_meta_stride = ALIGN(DIV_ROUND_UP(width, 32), 64);
  487. y_meta_plane = y_meta_stride * ALIGN(DIV_ROUND_UP(height, 8), 16);
  488. y_meta_plane = ALIGN(y_meta_plane, SZ_4K);
  489. y_stride = ALIGN(width, 128);
  490. y_plane = ALIGN(y_stride * ALIGN(height, 32), SZ_4K);
  491. uv_meta_stride = ALIGN(DIV_ROUND_UP(width / 2, 16), 64);
  492. uv_meta_plane = uv_meta_stride * ALIGN(DIV_ROUND_UP(height / 2, 8), 16);
  493. uv_meta_plane = ALIGN(uv_meta_plane, SZ_4K);
  494. uv_stride = ALIGN(width, 128);
  495. uv_plane = ALIGN(uv_stride * ALIGN(height / 2, 32), SZ_4K);
  496. return ALIGN(y_meta_plane + y_plane + uv_meta_plane + uv_plane +
  497. max(extradata, y_stride * 48), SZ_4K);
  498. }
  499. u32 venus_helper_get_framesz_raw(u32 hfi_fmt, u32 width, u32 height)
  500. {
  501. switch (hfi_fmt) {
  502. case HFI_COLOR_FORMAT_NV12:
  503. case HFI_COLOR_FORMAT_NV21:
  504. return get_framesize_raw_nv12(width, height);
  505. case HFI_COLOR_FORMAT_NV12_UBWC:
  506. return get_framesize_raw_nv12_ubwc(width, height);
  507. default:
  508. return 0;
  509. }
  510. }
  511. EXPORT_SYMBOL_GPL(venus_helper_get_framesz_raw);
  512. u32 venus_helper_get_framesz(u32 v4l2_fmt, u32 width, u32 height)
  513. {
  514. u32 hfi_fmt, sz;
  515. bool compressed;
  516. switch (v4l2_fmt) {
  517. case V4L2_PIX_FMT_MPEG:
  518. case V4L2_PIX_FMT_H264:
  519. case V4L2_PIX_FMT_H264_NO_SC:
  520. case V4L2_PIX_FMT_H264_MVC:
  521. case V4L2_PIX_FMT_H263:
  522. case V4L2_PIX_FMT_MPEG1:
  523. case V4L2_PIX_FMT_MPEG2:
  524. case V4L2_PIX_FMT_MPEG4:
  525. case V4L2_PIX_FMT_XVID:
  526. case V4L2_PIX_FMT_VC1_ANNEX_G:
  527. case V4L2_PIX_FMT_VC1_ANNEX_L:
  528. case V4L2_PIX_FMT_VP8:
  529. case V4L2_PIX_FMT_VP9:
  530. case V4L2_PIX_FMT_HEVC:
  531. compressed = true;
  532. break;
  533. default:
  534. compressed = false;
  535. break;
  536. }
  537. if (compressed) {
  538. sz = ALIGN(height, 32) * ALIGN(width, 32) * 3 / 2 / 2;
  539. return ALIGN(sz, SZ_4K);
  540. }
  541. hfi_fmt = to_hfi_raw_fmt(v4l2_fmt);
  542. if (!hfi_fmt)
  543. return 0;
  544. return venus_helper_get_framesz_raw(hfi_fmt, width, height);
  545. }
  546. EXPORT_SYMBOL_GPL(venus_helper_get_framesz);
  547. int venus_helper_set_input_resolution(struct venus_inst *inst,
  548. unsigned int width, unsigned int height)
  549. {
  550. u32 ptype = HFI_PROPERTY_PARAM_FRAME_SIZE;
  551. struct hfi_framesize fs;
  552. fs.buffer_type = HFI_BUFFER_INPUT;
  553. fs.width = width;
  554. fs.height = height;
  555. return hfi_session_set_property(inst, ptype, &fs);
  556. }
  557. EXPORT_SYMBOL_GPL(venus_helper_set_input_resolution);
  558. int venus_helper_set_output_resolution(struct venus_inst *inst,
  559. unsigned int width, unsigned int height,
  560. u32 buftype)
  561. {
  562. u32 ptype = HFI_PROPERTY_PARAM_FRAME_SIZE;
  563. struct hfi_framesize fs;
  564. fs.buffer_type = buftype;
  565. fs.width = width;
  566. fs.height = height;
  567. return hfi_session_set_property(inst, ptype, &fs);
  568. }
  569. EXPORT_SYMBOL_GPL(venus_helper_set_output_resolution);
  570. int venus_helper_set_work_mode(struct venus_inst *inst, u32 mode)
  571. {
  572. const u32 ptype = HFI_PROPERTY_PARAM_WORK_MODE;
  573. struct hfi_video_work_mode wm;
  574. if (!IS_V4(inst->core))
  575. return 0;
  576. wm.video_work_mode = mode;
  577. return hfi_session_set_property(inst, ptype, &wm);
  578. }
  579. EXPORT_SYMBOL_GPL(venus_helper_set_work_mode);
  580. int venus_helper_set_core_usage(struct venus_inst *inst, u32 usage)
  581. {
  582. const u32 ptype = HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE;
  583. struct hfi_videocores_usage_type cu;
  584. if (!IS_V4(inst->core))
  585. return 0;
  586. cu.video_core_enable_mask = usage;
  587. return hfi_session_set_property(inst, ptype, &cu);
  588. }
  589. EXPORT_SYMBOL_GPL(venus_helper_set_core_usage);
  590. int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs,
  591. unsigned int output_bufs,
  592. unsigned int output2_bufs)
  593. {
  594. u32 ptype = HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL;
  595. struct hfi_buffer_count_actual buf_count;
  596. int ret;
  597. buf_count.type = HFI_BUFFER_INPUT;
  598. buf_count.count_actual = input_bufs;
  599. ret = hfi_session_set_property(inst, ptype, &buf_count);
  600. if (ret)
  601. return ret;
  602. buf_count.type = HFI_BUFFER_OUTPUT;
  603. buf_count.count_actual = output_bufs;
  604. ret = hfi_session_set_property(inst, ptype, &buf_count);
  605. if (ret)
  606. return ret;
  607. if (output2_bufs) {
  608. buf_count.type = HFI_BUFFER_OUTPUT2;
  609. buf_count.count_actual = output2_bufs;
  610. ret = hfi_session_set_property(inst, ptype, &buf_count);
  611. }
  612. return ret;
  613. }
  614. EXPORT_SYMBOL_GPL(venus_helper_set_num_bufs);
  615. int venus_helper_set_raw_format(struct venus_inst *inst, u32 hfi_format,
  616. u32 buftype)
  617. {
  618. const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT;
  619. struct hfi_uncompressed_format_select fmt;
  620. fmt.buffer_type = buftype;
  621. fmt.format = hfi_format;
  622. return hfi_session_set_property(inst, ptype, &fmt);
  623. }
  624. EXPORT_SYMBOL_GPL(venus_helper_set_raw_format);
  625. int venus_helper_set_color_format(struct venus_inst *inst, u32 pixfmt)
  626. {
  627. u32 hfi_format, buftype;
  628. if (inst->session_type == VIDC_SESSION_TYPE_DEC)
  629. buftype = HFI_BUFFER_OUTPUT;
  630. else if (inst->session_type == VIDC_SESSION_TYPE_ENC)
  631. buftype = HFI_BUFFER_INPUT;
  632. else
  633. return -EINVAL;
  634. hfi_format = to_hfi_raw_fmt(pixfmt);
  635. if (!hfi_format)
  636. return -EINVAL;
  637. return venus_helper_set_raw_format(inst, hfi_format, buftype);
  638. }
  639. EXPORT_SYMBOL_GPL(venus_helper_set_color_format);
  640. int venus_helper_set_multistream(struct venus_inst *inst, bool out_en,
  641. bool out2_en)
  642. {
  643. struct hfi_multi_stream multi = {0};
  644. u32 ptype = HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM;
  645. int ret;
  646. multi.buffer_type = HFI_BUFFER_OUTPUT;
  647. multi.enable = out_en;
  648. ret = hfi_session_set_property(inst, ptype, &multi);
  649. if (ret)
  650. return ret;
  651. multi.buffer_type = HFI_BUFFER_OUTPUT2;
  652. multi.enable = out2_en;
  653. return hfi_session_set_property(inst, ptype, &multi);
  654. }
  655. EXPORT_SYMBOL_GPL(venus_helper_set_multistream);
  656. int venus_helper_set_dyn_bufmode(struct venus_inst *inst)
  657. {
  658. const u32 ptype = HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE;
  659. struct hfi_buffer_alloc_mode mode;
  660. int ret;
  661. if (!is_dynamic_bufmode(inst))
  662. return 0;
  663. mode.type = HFI_BUFFER_OUTPUT;
  664. mode.mode = HFI_BUFFER_MODE_DYNAMIC;
  665. ret = hfi_session_set_property(inst, ptype, &mode);
  666. if (ret)
  667. return ret;
  668. mode.type = HFI_BUFFER_OUTPUT2;
  669. return hfi_session_set_property(inst, ptype, &mode);
  670. }
  671. EXPORT_SYMBOL_GPL(venus_helper_set_dyn_bufmode);
  672. int venus_helper_set_bufsize(struct venus_inst *inst, u32 bufsize, u32 buftype)
  673. {
  674. const u32 ptype = HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL;
  675. struct hfi_buffer_size_actual bufsz;
  676. bufsz.type = buftype;
  677. bufsz.size = bufsize;
  678. return hfi_session_set_property(inst, ptype, &bufsz);
  679. }
  680. EXPORT_SYMBOL_GPL(venus_helper_set_bufsize);
  681. unsigned int venus_helper_get_opb_size(struct venus_inst *inst)
  682. {
  683. /* the encoder has only one output */
  684. if (inst->session_type == VIDC_SESSION_TYPE_ENC)
  685. return inst->output_buf_size;
  686. if (inst->opb_buftype == HFI_BUFFER_OUTPUT)
  687. return inst->output_buf_size;
  688. else if (inst->opb_buftype == HFI_BUFFER_OUTPUT2)
  689. return inst->output2_buf_size;
  690. return 0;
  691. }
  692. EXPORT_SYMBOL_GPL(venus_helper_get_opb_size);
  693. static void delayed_process_buf_func(struct work_struct *work)
  694. {
  695. struct venus_buffer *buf, *n;
  696. struct venus_inst *inst;
  697. int ret;
  698. inst = container_of(work, struct venus_inst, delayed_process_work);
  699. mutex_lock(&inst->lock);
  700. if (!(inst->streamon_out & inst->streamon_cap))
  701. goto unlock;
  702. list_for_each_entry_safe(buf, n, &inst->delayed_process, ref_list) {
  703. if (buf->flags & HFI_BUFFERFLAG_READONLY)
  704. continue;
  705. ret = session_process_buf(inst, &buf->vb);
  706. if (ret)
  707. return_buf_error(inst, &buf->vb);
  708. list_del_init(&buf->ref_list);
  709. }
  710. unlock:
  711. mutex_unlock(&inst->lock);
  712. }
  713. void venus_helper_release_buf_ref(struct venus_inst *inst, unsigned int idx)
  714. {
  715. struct venus_buffer *buf;
  716. list_for_each_entry(buf, &inst->registeredbufs, reg_list) {
  717. if (buf->vb.vb2_buf.index == idx) {
  718. buf->flags &= ~HFI_BUFFERFLAG_READONLY;
  719. schedule_work(&inst->delayed_process_work);
  720. break;
  721. }
  722. }
  723. }
  724. EXPORT_SYMBOL_GPL(venus_helper_release_buf_ref);
  725. void venus_helper_acquire_buf_ref(struct vb2_v4l2_buffer *vbuf)
  726. {
  727. struct venus_buffer *buf = to_venus_buffer(vbuf);
  728. buf->flags |= HFI_BUFFERFLAG_READONLY;
  729. }
  730. EXPORT_SYMBOL_GPL(venus_helper_acquire_buf_ref);
  731. static int is_buf_refed(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf)
  732. {
  733. struct venus_buffer *buf = to_venus_buffer(vbuf);
  734. if (buf->flags & HFI_BUFFERFLAG_READONLY) {
  735. list_add_tail(&buf->ref_list, &inst->delayed_process);
  736. schedule_work(&inst->delayed_process_work);
  737. return 1;
  738. }
  739. return 0;
  740. }
  741. struct vb2_v4l2_buffer *
  742. venus_helper_find_buf(struct venus_inst *inst, unsigned int type, u32 idx)
  743. {
  744. struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
  745. if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
  746. return v4l2_m2m_src_buf_remove_by_idx(m2m_ctx, idx);
  747. else
  748. return v4l2_m2m_dst_buf_remove_by_idx(m2m_ctx, idx);
  749. }
  750. EXPORT_SYMBOL_GPL(venus_helper_find_buf);
  751. int venus_helper_vb2_buf_init(struct vb2_buffer *vb)
  752. {
  753. struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
  754. struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
  755. struct venus_buffer *buf = to_venus_buffer(vbuf);
  756. struct sg_table *sgt;
  757. sgt = vb2_dma_sg_plane_desc(vb, 0);
  758. if (!sgt)
  759. return -EFAULT;
  760. buf->size = vb2_plane_size(vb, 0);
  761. buf->dma_addr = sg_dma_address(sgt->sgl);
  762. if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
  763. list_add_tail(&buf->reg_list, &inst->registeredbufs);
  764. return 0;
  765. }
  766. EXPORT_SYMBOL_GPL(venus_helper_vb2_buf_init);
  767. int venus_helper_vb2_buf_prepare(struct vb2_buffer *vb)
  768. {
  769. struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
  770. unsigned int out_buf_size = venus_helper_get_opb_size(inst);
  771. if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
  772. vb2_plane_size(vb, 0) < out_buf_size)
  773. return -EINVAL;
  774. if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
  775. vb2_plane_size(vb, 0) < inst->input_buf_size)
  776. return -EINVAL;
  777. return 0;
  778. }
  779. EXPORT_SYMBOL_GPL(venus_helper_vb2_buf_prepare);
  780. void venus_helper_vb2_buf_queue(struct vb2_buffer *vb)
  781. {
  782. struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
  783. struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
  784. struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
  785. int ret;
  786. mutex_lock(&inst->lock);
  787. v4l2_m2m_buf_queue(m2m_ctx, vbuf);
  788. if (!(inst->streamon_out & inst->streamon_cap))
  789. goto unlock;
  790. ret = is_buf_refed(inst, vbuf);
  791. if (ret)
  792. goto unlock;
  793. ret = session_process_buf(inst, vbuf);
  794. if (ret)
  795. return_buf_error(inst, vbuf);
  796. unlock:
  797. mutex_unlock(&inst->lock);
  798. }
  799. EXPORT_SYMBOL_GPL(venus_helper_vb2_buf_queue);
  800. void venus_helper_buffers_done(struct venus_inst *inst,
  801. enum vb2_buffer_state state)
  802. {
  803. struct vb2_v4l2_buffer *buf;
  804. while ((buf = v4l2_m2m_src_buf_remove(inst->m2m_ctx)))
  805. v4l2_m2m_buf_done(buf, state);
  806. while ((buf = v4l2_m2m_dst_buf_remove(inst->m2m_ctx)))
  807. v4l2_m2m_buf_done(buf, state);
  808. }
  809. EXPORT_SYMBOL_GPL(venus_helper_buffers_done);
  810. void venus_helper_vb2_stop_streaming(struct vb2_queue *q)
  811. {
  812. struct venus_inst *inst = vb2_get_drv_priv(q);
  813. struct venus_core *core = inst->core;
  814. int ret;
  815. mutex_lock(&inst->lock);
  816. if (inst->streamon_out & inst->streamon_cap) {
  817. ret = hfi_session_stop(inst);
  818. ret |= hfi_session_unload_res(inst);
  819. ret |= session_unregister_bufs(inst);
  820. ret |= intbufs_free(inst);
  821. ret |= hfi_session_deinit(inst);
  822. if (inst->session_error || core->sys_error)
  823. ret = -EIO;
  824. if (ret)
  825. hfi_session_abort(inst);
  826. venus_helper_free_dpb_bufs(inst);
  827. load_scale_clocks(core);
  828. INIT_LIST_HEAD(&inst->registeredbufs);
  829. }
  830. venus_helper_buffers_done(inst, VB2_BUF_STATE_ERROR);
  831. if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
  832. inst->streamon_out = 0;
  833. else
  834. inst->streamon_cap = 0;
  835. mutex_unlock(&inst->lock);
  836. }
  837. EXPORT_SYMBOL_GPL(venus_helper_vb2_stop_streaming);
  838. int venus_helper_vb2_start_streaming(struct venus_inst *inst)
  839. {
  840. struct venus_core *core = inst->core;
  841. int ret;
  842. ret = intbufs_alloc(inst);
  843. if (ret)
  844. return ret;
  845. ret = session_register_bufs(inst);
  846. if (ret)
  847. goto err_bufs_free;
  848. load_scale_clocks(core);
  849. ret = hfi_session_load_res(inst);
  850. if (ret)
  851. goto err_unreg_bufs;
  852. ret = hfi_session_start(inst);
  853. if (ret)
  854. goto err_unload_res;
  855. ret = venus_helper_queue_dpb_bufs(inst);
  856. if (ret)
  857. goto err_session_stop;
  858. return 0;
  859. err_session_stop:
  860. hfi_session_stop(inst);
  861. err_unload_res:
  862. hfi_session_unload_res(inst);
  863. err_unreg_bufs:
  864. session_unregister_bufs(inst);
  865. err_bufs_free:
  866. intbufs_free(inst);
  867. return ret;
  868. }
  869. EXPORT_SYMBOL_GPL(venus_helper_vb2_start_streaming);
  870. void venus_helper_m2m_device_run(void *priv)
  871. {
  872. struct venus_inst *inst = priv;
  873. struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
  874. struct v4l2_m2m_buffer *buf, *n;
  875. int ret;
  876. mutex_lock(&inst->lock);
  877. v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buf, n) {
  878. ret = session_process_buf(inst, &buf->vb);
  879. if (ret)
  880. return_buf_error(inst, &buf->vb);
  881. }
  882. v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buf, n) {
  883. ret = session_process_buf(inst, &buf->vb);
  884. if (ret)
  885. return_buf_error(inst, &buf->vb);
  886. }
  887. mutex_unlock(&inst->lock);
  888. }
  889. EXPORT_SYMBOL_GPL(venus_helper_m2m_device_run);
  890. void venus_helper_m2m_job_abort(void *priv)
  891. {
  892. struct venus_inst *inst = priv;
  893. v4l2_m2m_job_finish(inst->m2m_dev, inst->m2m_ctx);
  894. }
  895. EXPORT_SYMBOL_GPL(venus_helper_m2m_job_abort);
  896. void venus_helper_init_instance(struct venus_inst *inst)
  897. {
  898. if (inst->session_type == VIDC_SESSION_TYPE_DEC) {
  899. INIT_LIST_HEAD(&inst->delayed_process);
  900. INIT_WORK(&inst->delayed_process_work,
  901. delayed_process_buf_func);
  902. }
  903. }
  904. EXPORT_SYMBOL_GPL(venus_helper_init_instance);
  905. static bool find_fmt_from_caps(struct venus_caps *caps, u32 buftype, u32 fmt)
  906. {
  907. unsigned int i;
  908. for (i = 0; i < caps->num_fmts; i++) {
  909. if (caps->fmts[i].buftype == buftype &&
  910. caps->fmts[i].fmt == fmt)
  911. return true;
  912. }
  913. return false;
  914. }
  915. int venus_helper_get_out_fmts(struct venus_inst *inst, u32 v4l2_fmt,
  916. u32 *out_fmt, u32 *out2_fmt, bool ubwc)
  917. {
  918. struct venus_core *core = inst->core;
  919. struct venus_caps *caps;
  920. u32 ubwc_fmt, fmt = to_hfi_raw_fmt(v4l2_fmt);
  921. bool found, found_ubwc;
  922. *out_fmt = *out2_fmt = 0;
  923. if (!fmt)
  924. return -EINVAL;
  925. caps = venus_caps_by_codec(core, inst->hfi_codec, inst->session_type);
  926. if (!caps)
  927. return -EINVAL;
  928. if (ubwc) {
  929. ubwc_fmt = fmt | HFI_COLOR_FORMAT_UBWC_BASE;
  930. found_ubwc = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT,
  931. ubwc_fmt);
  932. found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2, fmt);
  933. if (found_ubwc && found) {
  934. *out_fmt = ubwc_fmt;
  935. *out2_fmt = fmt;
  936. return 0;
  937. }
  938. }
  939. found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT, fmt);
  940. if (found) {
  941. *out_fmt = fmt;
  942. *out2_fmt = 0;
  943. return 0;
  944. }
  945. found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2, fmt);
  946. if (found) {
  947. *out_fmt = 0;
  948. *out2_fmt = fmt;
  949. return 0;
  950. }
  951. return -EINVAL;
  952. }
  953. EXPORT_SYMBOL_GPL(venus_helper_get_out_fmts);
  954. int venus_helper_power_enable(struct venus_core *core, u32 session_type,
  955. bool enable)
  956. {
  957. void __iomem *ctrl, *stat;
  958. u32 val;
  959. int ret;
  960. if (!IS_V3(core) && !IS_V4(core))
  961. return 0;
  962. if (IS_V3(core)) {
  963. if (session_type == VIDC_SESSION_TYPE_DEC)
  964. ctrl = core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL;
  965. else
  966. ctrl = core->base + WRAPPER_VENC_VCODEC_POWER_CONTROL;
  967. if (enable)
  968. writel(0, ctrl);
  969. else
  970. writel(1, ctrl);
  971. return 0;
  972. }
  973. if (session_type == VIDC_SESSION_TYPE_DEC) {
  974. ctrl = core->base + WRAPPER_VCODEC0_MMCC_POWER_CONTROL;
  975. stat = core->base + WRAPPER_VCODEC0_MMCC_POWER_STATUS;
  976. } else {
  977. ctrl = core->base + WRAPPER_VCODEC1_MMCC_POWER_CONTROL;
  978. stat = core->base + WRAPPER_VCODEC1_MMCC_POWER_STATUS;
  979. }
  980. if (enable) {
  981. writel(0, ctrl);
  982. ret = readl_poll_timeout(stat, val, val & BIT(1), 1, 100);
  983. if (ret)
  984. return ret;
  985. } else {
  986. writel(1, ctrl);
  987. ret = readl_poll_timeout(stat, val, !(val & BIT(1)), 1, 100);
  988. if (ret)
  989. return ret;
  990. }
  991. return 0;
  992. }
  993. EXPORT_SYMBOL_GPL(venus_helper_power_enable);