venc_h264_if.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. /*
  2. * Copyright (c) 2016 MediaTek Inc.
  3. * Author: Jungchang Tsao <jungchang.tsao@mediatek.com>
  4. * Daniel Hsiao <daniel.hsiao@mediatek.com>
  5. * PoChun Lin <pochun.lin@mediatek.com>
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify
  9. * it under the terms of the GNU General Public License version 2 as
  10. * published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. */
  17. #include <linux/interrupt.h>
  18. #include <linux/kernel.h>
  19. #include <linux/slab.h>
  20. #include "../mtk_vcodec_drv.h"
  21. #include "../mtk_vcodec_util.h"
  22. #include "../mtk_vcodec_intr.h"
  23. #include "../mtk_vcodec_enc.h"
  24. #include "../mtk_vcodec_enc_pm.h"
  25. #include "../venc_drv_base.h"
  26. #include "../venc_ipi_msg.h"
  27. #include "../venc_vpu_if.h"
  28. #include "mtk_vpu.h"
  29. static const char h264_filler_marker[] = {0x0, 0x0, 0x0, 0x1, 0xc};
  30. #define H264_FILLER_MARKER_SIZE ARRAY_SIZE(h264_filler_marker)
  31. #define VENC_PIC_BITSTREAM_BYTE_CNT 0x0098
  32. /**
  33. * enum venc_h264_vpu_work_buf - h264 encoder buffer index
  34. */
  35. enum venc_h264_vpu_work_buf {
  36. VENC_H264_VPU_WORK_BUF_RC_INFO,
  37. VENC_H264_VPU_WORK_BUF_RC_CODE,
  38. VENC_H264_VPU_WORK_BUF_REC_LUMA,
  39. VENC_H264_VPU_WORK_BUF_REC_CHROMA,
  40. VENC_H264_VPU_WORK_BUF_REF_LUMA,
  41. VENC_H264_VPU_WORK_BUF_REF_CHROMA,
  42. VENC_H264_VPU_WORK_BUF_MV_INFO_1,
  43. VENC_H264_VPU_WORK_BUF_MV_INFO_2,
  44. VENC_H264_VPU_WORK_BUF_SKIP_FRAME,
  45. VENC_H264_VPU_WORK_BUF_MAX,
  46. };
  47. /**
  48. * enum venc_h264_bs_mode - for bs_mode argument in h264_enc_vpu_encode
  49. */
  50. enum venc_h264_bs_mode {
  51. H264_BS_MODE_SPS,
  52. H264_BS_MODE_PPS,
  53. H264_BS_MODE_FRAME,
  54. };
  55. /*
  56. * struct venc_h264_vpu_config - Structure for h264 encoder configuration
  57. * AP-W/R : AP is writer/reader on this item
  58. * VPU-W/R: VPU is write/reader on this item
  59. * @input_fourcc: input fourcc
  60. * @bitrate: target bitrate (in bps)
  61. * @pic_w: picture width. Picture size is visible stream resolution, in pixels,
  62. * to be used for display purposes; must be smaller or equal to buffer
  63. * size.
  64. * @pic_h: picture height
  65. * @buf_w: buffer width. Buffer size is stream resolution in pixels aligned to
  66. * hardware requirements.
  67. * @buf_h: buffer height
  68. * @gop_size: group of picture size (idr frame)
  69. * @intra_period: intra frame period
  70. * @framerate: frame rate in fps
  71. * @profile: as specified in standard
  72. * @level: as specified in standard
  73. * @wfd: WFD mode 1:on, 0:off
  74. */
  75. struct venc_h264_vpu_config {
  76. u32 input_fourcc;
  77. u32 bitrate;
  78. u32 pic_w;
  79. u32 pic_h;
  80. u32 buf_w;
  81. u32 buf_h;
  82. u32 gop_size;
  83. u32 intra_period;
  84. u32 framerate;
  85. u32 profile;
  86. u32 level;
  87. u32 wfd;
  88. };
  89. /*
  90. * struct venc_h264_vpu_buf - Structure for buffer information
  91. * AP-W/R : AP is writer/reader on this item
  92. * VPU-W/R: VPU is write/reader on this item
  93. * @iova: IO virtual address
  94. * @vpua: VPU side memory addr which is used by RC_CODE
  95. * @size: buffer size (in bytes)
  96. */
  97. struct venc_h264_vpu_buf {
  98. u32 iova;
  99. u32 vpua;
  100. u32 size;
  101. };
  102. /*
  103. * struct venc_h264_vsi - Structure for VPU driver control and info share
  104. * AP-W/R : AP is writer/reader on this item
  105. * VPU-W/R: VPU is write/reader on this item
  106. * This structure is allocated in VPU side and shared to AP side.
  107. * @config: h264 encoder configuration
  108. * @work_bufs: working buffer information in VPU side
  109. * The work_bufs here is for storing the 'size' info shared to AP side.
  110. * The similar item in struct venc_h264_inst is for memory allocation
  111. * in AP side. The AP driver will copy the 'size' from here to the one in
  112. * struct mtk_vcodec_mem, then invoke mtk_vcodec_mem_alloc to allocate
  113. * the buffer. After that, bypass the 'dma_addr' to the 'iova' field here for
  114. * register setting in VPU side.
  115. */
  116. struct venc_h264_vsi {
  117. struct venc_h264_vpu_config config;
  118. struct venc_h264_vpu_buf work_bufs[VENC_H264_VPU_WORK_BUF_MAX];
  119. };
  120. /*
  121. * struct venc_h264_inst - h264 encoder AP driver instance
  122. * @hw_base: h264 encoder hardware register base
  123. * @work_bufs: working buffer
  124. * @pps_buf: buffer to store the pps bitstream
  125. * @work_buf_allocated: working buffer allocated flag
  126. * @frm_cnt: encoded frame count
  127. * @prepend_hdr: when the v4l2 layer send VENC_SET_PARAM_PREPEND_HEADER cmd
  128. * through h264_enc_set_param interface, it will set this flag and prepend the
  129. * sps/pps in h264_enc_encode function.
  130. * @vpu_inst: VPU instance to exchange information between AP and VPU
  131. * @vsi: driver structure allocated by VPU side and shared to AP side for
  132. * control and info share
  133. * @ctx: context for v4l2 layer integration
  134. */
  135. struct venc_h264_inst {
  136. void __iomem *hw_base;
  137. struct mtk_vcodec_mem work_bufs[VENC_H264_VPU_WORK_BUF_MAX];
  138. struct mtk_vcodec_mem pps_buf;
  139. bool work_buf_allocated;
  140. unsigned int frm_cnt;
  141. unsigned int prepend_hdr;
  142. struct venc_vpu_inst vpu_inst;
  143. struct venc_h264_vsi *vsi;
  144. struct mtk_vcodec_ctx *ctx;
  145. };
  146. static inline u32 h264_read_reg(struct venc_h264_inst *inst, u32 addr)
  147. {
  148. return readl(inst->hw_base + addr);
  149. }
  150. static unsigned int h264_get_profile(struct venc_h264_inst *inst,
  151. unsigned int profile)
  152. {
  153. switch (profile) {
  154. case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
  155. return 66;
  156. case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
  157. return 77;
  158. case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
  159. return 100;
  160. case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
  161. mtk_vcodec_err(inst, "unsupported CONSTRAINED_BASELINE");
  162. return 0;
  163. case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
  164. mtk_vcodec_err(inst, "unsupported EXTENDED");
  165. return 0;
  166. default:
  167. mtk_vcodec_debug(inst, "unsupported profile %d", profile);
  168. return 100;
  169. }
  170. }
  171. static unsigned int h264_get_level(struct venc_h264_inst *inst,
  172. unsigned int level)
  173. {
  174. switch (level) {
  175. case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
  176. mtk_vcodec_err(inst, "unsupported 1B");
  177. return 0;
  178. case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
  179. return 10;
  180. case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
  181. return 11;
  182. case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
  183. return 12;
  184. case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
  185. return 13;
  186. case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
  187. return 20;
  188. case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
  189. return 21;
  190. case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
  191. return 22;
  192. case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
  193. return 30;
  194. case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
  195. return 31;
  196. case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
  197. return 32;
  198. case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
  199. return 40;
  200. case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
  201. return 41;
  202. case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
  203. return 42;
  204. default:
  205. mtk_vcodec_debug(inst, "unsupported level %d", level);
  206. return 31;
  207. }
  208. }
  209. static void h264_enc_free_work_buf(struct venc_h264_inst *inst)
  210. {
  211. int i;
  212. mtk_vcodec_debug_enter(inst);
  213. /* Except the SKIP_FRAME buffers,
  214. * other buffers need to be freed by AP.
  215. */
  216. for (i = 0; i < VENC_H264_VPU_WORK_BUF_MAX; i++) {
  217. if (i != VENC_H264_VPU_WORK_BUF_SKIP_FRAME)
  218. mtk_vcodec_mem_free(inst->ctx, &inst->work_bufs[i]);
  219. }
  220. mtk_vcodec_mem_free(inst->ctx, &inst->pps_buf);
  221. mtk_vcodec_debug_leave(inst);
  222. }
  223. static int h264_enc_alloc_work_buf(struct venc_h264_inst *inst)
  224. {
  225. int i;
  226. int ret = 0;
  227. struct venc_h264_vpu_buf *wb = inst->vsi->work_bufs;
  228. mtk_vcodec_debug_enter(inst);
  229. for (i = 0; i < VENC_H264_VPU_WORK_BUF_MAX; i++) {
  230. /*
  231. * This 'wb' structure is set by VPU side and shared to AP for
  232. * buffer allocation and IO virtual addr mapping. For most of
  233. * the buffers, AP will allocate the buffer according to 'size'
  234. * field and store the IO virtual addr in 'iova' field. There
  235. * are two exceptions:
  236. * (1) RC_CODE buffer, it's pre-allocated in the VPU side, and
  237. * save the VPU addr in the 'vpua' field. The AP will translate
  238. * the VPU addr to the corresponding IO virtual addr and store
  239. * in 'iova' field for reg setting in VPU side.
  240. * (2) SKIP_FRAME buffer, it's pre-allocated in the VPU side,
  241. * and save the VPU addr in the 'vpua' field. The AP will
  242. * translate the VPU addr to the corresponding AP side virtual
  243. * address and do some memcpy access to move to bitstream buffer
  244. * assigned by v4l2 layer.
  245. */
  246. inst->work_bufs[i].size = wb[i].size;
  247. if (i == VENC_H264_VPU_WORK_BUF_SKIP_FRAME) {
  248. inst->work_bufs[i].va = vpu_mapping_dm_addr(
  249. inst->vpu_inst.dev, wb[i].vpua);
  250. inst->work_bufs[i].dma_addr = 0;
  251. } else {
  252. ret = mtk_vcodec_mem_alloc(inst->ctx,
  253. &inst->work_bufs[i]);
  254. if (ret) {
  255. mtk_vcodec_err(inst,
  256. "cannot allocate buf %d", i);
  257. goto err_alloc;
  258. }
  259. /*
  260. * This RC_CODE is pre-allocated by VPU and saved in VPU
  261. * addr. So we need use memcpy to copy RC_CODE from VPU
  262. * addr into IO virtual addr in 'iova' field for reg
  263. * setting in VPU side.
  264. */
  265. if (i == VENC_H264_VPU_WORK_BUF_RC_CODE) {
  266. void *tmp_va;
  267. tmp_va = vpu_mapping_dm_addr(inst->vpu_inst.dev,
  268. wb[i].vpua);
  269. memcpy(inst->work_bufs[i].va, tmp_va,
  270. wb[i].size);
  271. }
  272. }
  273. wb[i].iova = inst->work_bufs[i].dma_addr;
  274. mtk_vcodec_debug(inst,
  275. "work_buf[%d] va=0x%p iova=%pad size=%zu",
  276. i, inst->work_bufs[i].va,
  277. &inst->work_bufs[i].dma_addr,
  278. inst->work_bufs[i].size);
  279. }
  280. /* the pps_buf is used by AP side only */
  281. inst->pps_buf.size = 128;
  282. ret = mtk_vcodec_mem_alloc(inst->ctx, &inst->pps_buf);
  283. if (ret) {
  284. mtk_vcodec_err(inst, "cannot allocate pps_buf");
  285. goto err_alloc;
  286. }
  287. mtk_vcodec_debug_leave(inst);
  288. return ret;
  289. err_alloc:
  290. h264_enc_free_work_buf(inst);
  291. return ret;
  292. }
  293. static unsigned int h264_enc_wait_venc_done(struct venc_h264_inst *inst)
  294. {
  295. unsigned int irq_status = 0;
  296. struct mtk_vcodec_ctx *ctx = (struct mtk_vcodec_ctx *)inst->ctx;
  297. if (!mtk_vcodec_wait_for_done_ctx(ctx, MTK_INST_IRQ_RECEIVED,
  298. WAIT_INTR_TIMEOUT_MS)) {
  299. irq_status = ctx->irq_status;
  300. mtk_vcodec_debug(inst, "irq_status %x <-", irq_status);
  301. }
  302. return irq_status;
  303. }
  304. static int h264_encode_sps(struct venc_h264_inst *inst,
  305. struct mtk_vcodec_mem *bs_buf,
  306. unsigned int *bs_size)
  307. {
  308. int ret = 0;
  309. unsigned int irq_status;
  310. mtk_vcodec_debug_enter(inst);
  311. ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_SPS, NULL,
  312. bs_buf, bs_size);
  313. if (ret)
  314. return ret;
  315. irq_status = h264_enc_wait_venc_done(inst);
  316. if (irq_status != MTK_VENC_IRQ_STATUS_SPS) {
  317. mtk_vcodec_err(inst, "expect irq status %d",
  318. MTK_VENC_IRQ_STATUS_SPS);
  319. return -EINVAL;
  320. }
  321. *bs_size = h264_read_reg(inst, VENC_PIC_BITSTREAM_BYTE_CNT);
  322. mtk_vcodec_debug(inst, "bs size %d <-", *bs_size);
  323. return ret;
  324. }
  325. static int h264_encode_pps(struct venc_h264_inst *inst,
  326. struct mtk_vcodec_mem *bs_buf,
  327. unsigned int *bs_size)
  328. {
  329. int ret = 0;
  330. unsigned int irq_status;
  331. mtk_vcodec_debug_enter(inst);
  332. ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_PPS, NULL,
  333. bs_buf, bs_size);
  334. if (ret)
  335. return ret;
  336. irq_status = h264_enc_wait_venc_done(inst);
  337. if (irq_status != MTK_VENC_IRQ_STATUS_PPS) {
  338. mtk_vcodec_err(inst, "expect irq status %d",
  339. MTK_VENC_IRQ_STATUS_PPS);
  340. return -EINVAL;
  341. }
  342. *bs_size = h264_read_reg(inst, VENC_PIC_BITSTREAM_BYTE_CNT);
  343. mtk_vcodec_debug(inst, "bs size %d <-", *bs_size);
  344. return ret;
  345. }
  346. static int h264_encode_header(struct venc_h264_inst *inst,
  347. struct mtk_vcodec_mem *bs_buf,
  348. unsigned int *bs_size)
  349. {
  350. int ret = 0;
  351. unsigned int bs_size_sps;
  352. unsigned int bs_size_pps;
  353. ret = h264_encode_sps(inst, bs_buf, &bs_size_sps);
  354. if (ret)
  355. return ret;
  356. ret = h264_encode_pps(inst, &inst->pps_buf, &bs_size_pps);
  357. if (ret)
  358. return ret;
  359. memcpy(bs_buf->va + bs_size_sps, inst->pps_buf.va, bs_size_pps);
  360. *bs_size = bs_size_sps + bs_size_pps;
  361. return ret;
  362. }
  363. static int h264_encode_frame(struct venc_h264_inst *inst,
  364. struct venc_frm_buf *frm_buf,
  365. struct mtk_vcodec_mem *bs_buf,
  366. unsigned int *bs_size)
  367. {
  368. int ret = 0;
  369. unsigned int irq_status;
  370. mtk_vcodec_debug_enter(inst);
  371. ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_FRAME, frm_buf,
  372. bs_buf, bs_size);
  373. if (ret)
  374. return ret;
  375. /*
  376. * skip frame case: The skip frame buffer is composed by vpu side only,
  377. * it does not trigger the hw, so skip the wait interrupt operation.
  378. */
  379. if (inst->vpu_inst.state == VEN_IPI_MSG_ENC_STATE_SKIP) {
  380. *bs_size = inst->vpu_inst.bs_size;
  381. memcpy(bs_buf->va,
  382. inst->work_bufs[VENC_H264_VPU_WORK_BUF_SKIP_FRAME].va,
  383. *bs_size);
  384. ++inst->frm_cnt;
  385. return ret;
  386. }
  387. irq_status = h264_enc_wait_venc_done(inst);
  388. if (irq_status != MTK_VENC_IRQ_STATUS_FRM) {
  389. mtk_vcodec_err(inst, "irq_status=%d failed", irq_status);
  390. return -EIO;
  391. }
  392. *bs_size = h264_read_reg(inst, VENC_PIC_BITSTREAM_BYTE_CNT);
  393. ++inst->frm_cnt;
  394. mtk_vcodec_debug(inst, "frm %d bs_size %d key_frm %d <-",
  395. inst->frm_cnt, *bs_size, inst->vpu_inst.is_key_frm);
  396. return ret;
  397. }
  398. static void h264_encode_filler(struct venc_h264_inst *inst, void *buf,
  399. int size)
  400. {
  401. unsigned char *p = buf;
  402. if (size < H264_FILLER_MARKER_SIZE) {
  403. mtk_vcodec_err(inst, "filler size too small %d", size);
  404. return;
  405. }
  406. memcpy(p, h264_filler_marker, ARRAY_SIZE(h264_filler_marker));
  407. size -= H264_FILLER_MARKER_SIZE;
  408. p += H264_FILLER_MARKER_SIZE;
  409. memset(p, 0xff, size);
  410. }
  411. static int h264_enc_init(struct mtk_vcodec_ctx *ctx, unsigned long *handle)
  412. {
  413. int ret = 0;
  414. struct venc_h264_inst *inst;
  415. inst = kzalloc(sizeof(*inst), GFP_KERNEL);
  416. if (!inst)
  417. return -ENOMEM;
  418. inst->ctx = ctx;
  419. inst->vpu_inst.ctx = ctx;
  420. inst->vpu_inst.dev = ctx->dev->vpu_plat_dev;
  421. inst->vpu_inst.id = IPI_VENC_H264;
  422. inst->hw_base = mtk_vcodec_get_reg_addr(inst->ctx, VENC_SYS);
  423. mtk_vcodec_debug_enter(inst);
  424. ret = vpu_enc_init(&inst->vpu_inst);
  425. inst->vsi = (struct venc_h264_vsi *)inst->vpu_inst.vsi;
  426. mtk_vcodec_debug_leave(inst);
  427. if (ret)
  428. kfree(inst);
  429. else
  430. (*handle) = (unsigned long)inst;
  431. return ret;
  432. }
  433. static int h264_enc_encode(unsigned long handle,
  434. enum venc_start_opt opt,
  435. struct venc_frm_buf *frm_buf,
  436. struct mtk_vcodec_mem *bs_buf,
  437. struct venc_done_result *result)
  438. {
  439. int ret = 0;
  440. struct venc_h264_inst *inst = (struct venc_h264_inst *)handle;
  441. struct mtk_vcodec_ctx *ctx = inst->ctx;
  442. mtk_vcodec_debug(inst, "opt %d ->", opt);
  443. enable_irq(ctx->dev->enc_irq);
  444. switch (opt) {
  445. case VENC_START_OPT_ENCODE_SEQUENCE_HEADER: {
  446. unsigned int bs_size_hdr;
  447. ret = h264_encode_header(inst, bs_buf, &bs_size_hdr);
  448. if (ret)
  449. goto encode_err;
  450. result->bs_size = bs_size_hdr;
  451. result->is_key_frm = false;
  452. break;
  453. }
  454. case VENC_START_OPT_ENCODE_FRAME: {
  455. int hdr_sz;
  456. int hdr_sz_ext;
  457. int filler_sz = 0;
  458. const int bs_alignment = 128;
  459. struct mtk_vcodec_mem tmp_bs_buf;
  460. unsigned int bs_size_hdr;
  461. unsigned int bs_size_frm;
  462. if (!inst->prepend_hdr) {
  463. ret = h264_encode_frame(inst, frm_buf, bs_buf,
  464. &result->bs_size);
  465. if (ret)
  466. goto encode_err;
  467. result->is_key_frm = inst->vpu_inst.is_key_frm;
  468. break;
  469. }
  470. mtk_vcodec_debug(inst, "h264_encode_frame prepend SPS/PPS");
  471. ret = h264_encode_header(inst, bs_buf, &bs_size_hdr);
  472. if (ret)
  473. goto encode_err;
  474. hdr_sz = bs_size_hdr;
  475. hdr_sz_ext = (hdr_sz & (bs_alignment - 1));
  476. if (hdr_sz_ext) {
  477. filler_sz = bs_alignment - hdr_sz_ext;
  478. if (hdr_sz_ext + H264_FILLER_MARKER_SIZE > bs_alignment)
  479. filler_sz += bs_alignment;
  480. h264_encode_filler(inst, bs_buf->va + hdr_sz,
  481. filler_sz);
  482. }
  483. tmp_bs_buf.va = bs_buf->va + hdr_sz + filler_sz;
  484. tmp_bs_buf.dma_addr = bs_buf->dma_addr + hdr_sz + filler_sz;
  485. tmp_bs_buf.size = bs_buf->size - (hdr_sz + filler_sz);
  486. ret = h264_encode_frame(inst, frm_buf, &tmp_bs_buf,
  487. &bs_size_frm);
  488. if (ret)
  489. goto encode_err;
  490. result->bs_size = hdr_sz + filler_sz + bs_size_frm;
  491. mtk_vcodec_debug(inst, "hdr %d filler %d frame %d bs %d",
  492. hdr_sz, filler_sz, bs_size_frm,
  493. result->bs_size);
  494. inst->prepend_hdr = 0;
  495. result->is_key_frm = inst->vpu_inst.is_key_frm;
  496. break;
  497. }
  498. default:
  499. mtk_vcodec_err(inst, "venc_start_opt %d not supported", opt);
  500. ret = -EINVAL;
  501. break;
  502. }
  503. encode_err:
  504. disable_irq(ctx->dev->enc_irq);
  505. mtk_vcodec_debug(inst, "opt %d <-", opt);
  506. return ret;
  507. }
  508. static int h264_enc_set_param(unsigned long handle,
  509. enum venc_set_param_type type,
  510. struct venc_enc_param *enc_prm)
  511. {
  512. int ret = 0;
  513. struct venc_h264_inst *inst = (struct venc_h264_inst *)handle;
  514. mtk_vcodec_debug(inst, "->type=%d", type);
  515. switch (type) {
  516. case VENC_SET_PARAM_ENC:
  517. inst->vsi->config.input_fourcc = enc_prm->input_yuv_fmt;
  518. inst->vsi->config.bitrate = enc_prm->bitrate;
  519. inst->vsi->config.pic_w = enc_prm->width;
  520. inst->vsi->config.pic_h = enc_prm->height;
  521. inst->vsi->config.buf_w = enc_prm->buf_width;
  522. inst->vsi->config.buf_h = enc_prm->buf_height;
  523. inst->vsi->config.gop_size = enc_prm->gop_size;
  524. inst->vsi->config.framerate = enc_prm->frm_rate;
  525. inst->vsi->config.intra_period = enc_prm->intra_period;
  526. inst->vsi->config.profile =
  527. h264_get_profile(inst, enc_prm->h264_profile);
  528. inst->vsi->config.level =
  529. h264_get_level(inst, enc_prm->h264_level);
  530. inst->vsi->config.wfd = 0;
  531. ret = vpu_enc_set_param(&inst->vpu_inst, type, enc_prm);
  532. if (ret)
  533. break;
  534. if (inst->work_buf_allocated) {
  535. h264_enc_free_work_buf(inst);
  536. inst->work_buf_allocated = false;
  537. }
  538. ret = h264_enc_alloc_work_buf(inst);
  539. if (ret)
  540. break;
  541. inst->work_buf_allocated = true;
  542. break;
  543. case VENC_SET_PARAM_PREPEND_HEADER:
  544. inst->prepend_hdr = 1;
  545. mtk_vcodec_debug(inst, "set prepend header mode");
  546. break;
  547. default:
  548. ret = vpu_enc_set_param(&inst->vpu_inst, type, enc_prm);
  549. break;
  550. }
  551. mtk_vcodec_debug_leave(inst);
  552. return ret;
  553. }
  554. static int h264_enc_deinit(unsigned long handle)
  555. {
  556. int ret = 0;
  557. struct venc_h264_inst *inst = (struct venc_h264_inst *)handle;
  558. mtk_vcodec_debug_enter(inst);
  559. ret = vpu_enc_deinit(&inst->vpu_inst);
  560. if (inst->work_buf_allocated)
  561. h264_enc_free_work_buf(inst);
  562. mtk_vcodec_debug_leave(inst);
  563. kfree(inst);
  564. return ret;
  565. }
  566. static const struct venc_common_if venc_h264_if = {
  567. h264_enc_init,
  568. h264_enc_encode,
  569. h264_enc_set_param,
  570. h264_enc_deinit,
  571. };
  572. const struct venc_common_if *get_h264_enc_comm_if(void);
  573. const struct venc_common_if *get_h264_enc_comm_if(void)
  574. {
  575. return &venc_h264_if;
  576. }