diff --git a/arch/arm/boot/dts/broadcom/bcm2711.dtsi b/arch/arm/boot/dts/broadcom/bcm2711.dtsi index bb137d8da1a821..3c76cb28fd0e78 100644 --- a/arch/arm/boot/dts/broadcom/bcm2711.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm2711.dtsi @@ -614,7 +614,7 @@ }; hevc_dec: codec@7eb10000 { - compatible = "brcm,bcm2711-hevc-dec", "raspberrypi,hevc-dec"; + compatible = "brcm,bcm2711-hevc-dec"; reg = <0x0 0x7eb00000 0x10000>, /* HEVC */ <0x0 0x7eb10000 0x1000>; /* INTC */ reg-names = "hevc", diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-ds.dtsi b/arch/arm64/boot/dts/broadcom/bcm2712-ds.dtsi index 95482c40a9eb57..3574a6c4b9c3b8 100644 --- a/arch/arm64/boot/dts/broadcom/bcm2712-ds.dtsi +++ b/arch/arm64/boot/dts/broadcom/bcm2712-ds.dtsi @@ -369,7 +369,7 @@ }; hevc_dec: codec@800000 { - compatible = "brcm,bcm2712-hevc-dec", "raspberrypi,hevc-dec"; + compatible = "brcm,bcm2712-hevc-dec", "brcm,bcm2711-hevc-dec"; reg = <0x10 0x00800000 0x0 0x10000>, /* HEVC */ <0x10 0x00840000 0x0 0x1000>; /* INTC */ reg-names = "hevc", diff --git a/drivers/media/platform/raspberrypi/hevc_dec/hevc_d.c b/drivers/media/platform/raspberrypi/hevc_dec/hevc_d.c index dee978882f82f9..30a382b65c0a57 100644 --- a/drivers/media/platform/raspberrypi/hevc_dec/hevc_d.c +++ b/drivers/media/platform/raspberrypi/hevc_dec/hevc_d.c @@ -25,6 +25,10 @@ #include "hevc_d_video.h" #include "hevc_d_hw.h" +int hevc_d_v4l2_debug; +module_param_named(debug, hevc_d_v4l2_debug, int, 0644); +MODULE_PARM_DESC(debug, "Debug level 0-2"); + /* * Default /dev/videoN node number. * Deliberately avoid the very low numbers as these are often taken by webcams @@ -34,54 +38,33 @@ static int video_nr = 19; module_param(video_nr, int, 0644); MODULE_PARM_DESC(video_nr, "decoder video device number"); -static const struct hevc_d_control hevc_d_ctrls[] = { +static const struct v4l2_ctrl_config hevc_d_ctrls[] = { { - .cfg = { - .id = V4L2_CID_STATELESS_HEVC_SPS, - .ops = &hevc_d_hevc_sps_ctrl_ops, - }, - .required = false, + .id = V4L2_CID_STATELESS_HEVC_SPS, + .ops = &hevc_d_hevc_sps_ctrl_ops, }, { - .cfg = { - .id = V4L2_CID_STATELESS_HEVC_PPS, - .ops = &hevc_d_hevc_pps_ctrl_ops, - }, - .required = false, + .id = V4L2_CID_STATELESS_HEVC_PPS, + .ops = &hevc_d_hevc_pps_ctrl_ops, }, { - .cfg = { - .id = V4L2_CID_STATELESS_HEVC_SCALING_MATRIX, - }, - .required = false, + .id = V4L2_CID_STATELESS_HEVC_SCALING_MATRIX, }, { - .cfg = { - .id = V4L2_CID_STATELESS_HEVC_DECODE_PARAMS, - }, - .required = true, + .id = V4L2_CID_STATELESS_HEVC_DECODE_PARAMS, }, { - .cfg = { - .name = "Slice param array", - .id = V4L2_CID_STATELESS_HEVC_SLICE_PARAMS, - .type = V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS, - .flags = V4L2_CTRL_FLAG_DYNAMIC_ARRAY, - .dims = { 0x1000 }, - }, - .required = true, + .name = "Slice param array", + .id = V4L2_CID_STATELESS_HEVC_SLICE_PARAMS, + .type = V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS, + .flags = V4L2_CTRL_FLAG_DYNAMIC_ARRAY, + .dims = { 0x1000 }, }, { - .cfg = { - .id = V4L2_CID_STATELESS_HEVC_DECODE_MODE, - .min = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED, - .max = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED, - .def = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED, - }, - .required = false, + .id = V4L2_CID_STATELESS_HEVC_DECODE_MODE, + .min = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED, + .max = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED, + .def = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED, }, { - .cfg = { - .id = V4L2_CID_STATELESS_HEVC_START_CODE, - .min = V4L2_STATELESS_HEVC_START_CODE_NONE, - .max = V4L2_STATELESS_HEVC_START_CODE_ANNEX_B, - .def = V4L2_STATELESS_HEVC_START_CODE_NONE, - }, - .required = false, + .id = V4L2_CID_STATELESS_HEVC_START_CODE, + .min = V4L2_STATELESS_HEVC_START_CODE_NONE, + .max = V4L2_STATELESS_HEVC_START_CODE_ANNEX_B, + .def = V4L2_STATELESS_HEVC_START_CODE_NONE, }, }; @@ -123,12 +106,11 @@ static int hevc_d_init_ctrls(struct hevc_d_dev *dev, struct hevc_d_ctx *ctx) return -ENOMEM; for (i = 0; i < HEVC_D_CTRLS_COUNT; i++) { - ctrl = v4l2_ctrl_new_custom(hdl, &hevc_d_ctrls[i].cfg, - ctx); + ctrl = v4l2_ctrl_new_custom(hdl, &hevc_d_ctrls[i], ctx); if (hdl->error) { v4l2_err(&dev->v4l2_dev, "Failed to create new custom control id=%#x\n", - hevc_d_ctrls[i].cfg.id); + hevc_d_ctrls[i].id); v4l2_ctrl_handler_free(hdl); kfree(ctx->ctrls); @@ -144,69 +126,6 @@ static int hevc_d_init_ctrls(struct hevc_d_dev *dev, struct hevc_d_ctx *ctx) return 0; } -static int hevc_d_request_validate(struct media_request *req) -{ - struct media_request_object *obj; - struct v4l2_ctrl_handler *parent_hdl, *hdl; - struct hevc_d_ctx *ctx = NULL; - struct v4l2_ctrl *ctrl_test; - unsigned int count; - unsigned int i; - - list_for_each_entry(obj, &req->objects, list) { - struct vb2_buffer *vb; - - if (vb2_request_object_is_buffer(obj)) { - vb = container_of(obj, struct vb2_buffer, req_obj); - ctx = vb2_get_drv_priv(vb->vb2_queue); - - break; - } - } - - if (!ctx) - return -ENOENT; - - count = vb2_request_buffer_cnt(req); - if (!count) { - v4l2_info(&ctx->dev->v4l2_dev, - "No buffer was provided with the request\n"); - return -ENOENT; - } else if (count > 1) { - v4l2_info(&ctx->dev->v4l2_dev, - "More than one buffer was provided with the request\n"); - return -EINVAL; - } - - parent_hdl = &ctx->hdl; - - hdl = v4l2_ctrl_request_hdl_find(req, parent_hdl); - if (!hdl) { - v4l2_info(&ctx->dev->v4l2_dev, "Missing codec control(s)\n"); - return -ENOENT; - } - - for (i = 0; i < HEVC_D_CTRLS_COUNT; i++) { - if (!hevc_d_ctrls[i].required) - continue; - - ctrl_test = - v4l2_ctrl_request_hdl_ctrl_find(hdl, - hevc_d_ctrls[i].cfg.id); - if (!ctrl_test) { - v4l2_info(&ctx->dev->v4l2_dev, - "Missing required codec control %d: id=%#x\n", - i, hevc_d_ctrls[i].cfg.id); - v4l2_ctrl_request_hdl_put(hdl); - return -ENOENT; - } - } - - v4l2_ctrl_request_hdl_put(hdl); - - return vb2_request_validate(req); -} - static int hevc_d_open(struct file *file) { struct hevc_d_dev *dev = video_drvdata(file); @@ -229,17 +148,17 @@ static int hevc_d_open(struct file *file) file->private_data = &ctx->fh; ctx->dev = dev; - ret = hevc_d_init_ctrls(dev, ctx); - if (ret) - goto err_free; - ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &hevc_d_queue_init); if (IS_ERR(ctx->fh.m2m_ctx)) { ret = PTR_ERR(ctx->fh.m2m_ctx); - goto err_ctrls; + goto err_free; } + ret = hevc_d_init_ctrls(dev, ctx); + if (ret) + goto err_ctx; + /* The only bit of format info that we can guess now is H265 src * Everything else we need more info for */ @@ -251,9 +170,8 @@ static int hevc_d_open(struct file *file) return 0; -err_ctrls: - v4l2_ctrl_handler_free(&ctx->hdl); - kfree(ctx->ctrls); +err_ctx: + v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); err_free: mutex_destroy(&ctx->ctx_mutex); kfree(ctx); @@ -272,11 +190,12 @@ static int hevc_d_release(struct file *file) mutex_lock(&dev->dev_mutex); v4l2_fh_del(&ctx->fh); - v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); v4l2_ctrl_handler_free(&ctx->hdl); kfree(ctx->ctrls); + v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); + v4l2_fh_exit(&ctx->fh); mutex_destroy(&ctx->ctx_mutex); @@ -317,7 +236,7 @@ static const struct v4l2_m2m_ops hevc_d_m2m_ops = { }; static const struct media_device_ops hevc_d_m2m_media_ops = { - .req_validate = hevc_d_request_validate, + .req_validate = vb2_request_validate, .req_queue = hevc_d_media_req_queue, }; @@ -439,7 +358,7 @@ static void hevc_d_remove(struct platform_device *pdev) } static const struct of_device_id hevc_d_dt_match[] = { - { .compatible = "raspberrypi,hevc-dec", }, + { .compatible = "brcm,bcm2711-hevc-dec", }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, hevc_d_dt_match); diff --git a/drivers/media/platform/raspberrypi/hevc_dec/hevc_d.h b/drivers/media/platform/raspberrypi/hevc_dec/hevc_d.h index 37c2d1612d2a4b..f3ae7d3b5cc17e 100644 --- a/drivers/media/platform/raspberrypi/hevc_dec/hevc_d.h +++ b/drivers/media/platform/raspberrypi/hevc_dec/hevc_d.h @@ -22,28 +22,36 @@ #include #include -#define HEVC_D_DEC_ENV_COUNT 6 +/* + * Q sizes of 3 give one entry being prepared, one waiting and + * one processing. Testing shows no advantage to greater Q depths + */ + +/* + * Max processing Q size Phase 0 -> Phase 1 + * This is per open context + */ #define HEVC_D_P1BUF_COUNT 3 +/* + * Max processing Q size Phase 1 -> Phase 2 + * This is per device + */ #define HEVC_D_P2BUF_COUNT 3 +/* + * Number of decode environments a context has + * There is no independent flow control on this number so it must be + * capable of holding P1 + P2 entries. + */ +#define HEVC_D_DEC_ENV_COUNT (HEVC_D_P1BUF_COUNT + HEVC_D_P2BUF_COUNT) #define HEVC_D_NAME "rpi-hevc-dec" -#define HEVC_D_CAPABILITY_UNTILED BIT(0) -#define HEVC_D_CAPABILITY_H265_DEC BIT(1) - -#define HEVC_D_QUIRK_NO_DMA_OFFSET BIT(0) - enum hevc_d_irq_status { HEVC_D_IRQ_NONE, HEVC_D_IRQ_ERROR, HEVC_D_IRQ_OK, }; -struct hevc_d_control { - struct v4l2_ctrl_config cfg; - unsigned char required:1; -}; - struct hevc_d_h265_run { u32 slice_ents; const struct v4l2_ctrl_hevc_sps *sps; @@ -88,9 +96,6 @@ struct hevc_d_ctx { struct v4l2_pix_format_mplane dst_fmt; int dst_fmt_set; - int src_stream_on; - int dst_stream_on; - /* * fatal_err is set if an error has occurred s.t. decode cannot * continue (such as running out of CMA) @@ -133,12 +138,6 @@ struct hevc_d_ctx { unsigned int colmv_picsize; }; -struct hevc_d_variant { - unsigned int capabilities; - unsigned int quirks; - unsigned int mod_rate; -}; - struct hevc_d_hw_irq_ent; #define HEVC_D_ICTL_ENABLE_UNLIMITED (-1) @@ -183,6 +182,10 @@ struct hevc_d_dev { struct hevc_d_hw_irq_ctrl ic_active2; }; +extern int hevc_d_v4l2_debug; +#define hevc_d_dbg(level, dev, fmt, arg...)\ + v4l2_dbg((level), hevc_d_v4l2_debug, (dev), fmt, ## arg) + struct v4l2_ctrl *hevc_d_find_ctrl(struct hevc_d_ctx *ctx, u32 id); void *hevc_d_find_control_data(struct hevc_d_ctx *ctx, u32 id); diff --git a/drivers/media/platform/raspberrypi/hevc_dec/hevc_d_h265.c b/drivers/media/platform/raspberrypi/hevc_dec/hevc_d_h265.c index 6c9a9d6db15a54..ef8c01feb0840c 100644 --- a/drivers/media/platform/raspberrypi/hevc_dec/hevc_d_h265.c +++ b/drivers/media/platform/raspberrypi/hevc_dec/hevc_d_h265.c @@ -21,6 +21,9 @@ #include "hevc_d_hw.h" #include "hevc_d_video.h" +/* Maximum length of command buffer before we rate it an error */ +#define CMD_BUFFER_SIZE_MAX 0x100000 + enum hevc_slice_type { HEVC_SLICE_B = 0, HEVC_SLICE_P = 1, @@ -206,6 +209,7 @@ struct hevc_d_dec_state { /* Slice vars */ unsigned int slice_idx; + unsigned int idx_inuse; bool slice_temporal_mvp; /* Slice flag but constant for frame */ bool use_aux; bool mk_aux; @@ -216,7 +220,7 @@ struct hevc_d_dec_state { const struct v4l2_ctrl_hevc_decode_params *dec; unsigned int nb_refs[2]; unsigned int slice_qp; - unsigned int max_num_merge_cand; // 0 if I-slice + unsigned int max_num_merge_cand; /* 0 if I-slice */ bool dependent_slice_segment_flag; unsigned int start_ts; /* slice_segment_addr -> ts */ @@ -226,18 +230,13 @@ struct hevc_d_dec_state { unsigned int prev_ctb_y; }; -static inline int clip_int(const int x, const int lo, const int hi) -{ - return x < lo ? lo : x > hi ? hi : x; -} - /* Phase 1 command and bit FIFOs */ static int cmds_check_space(struct hevc_d_dec_env *const de, unsigned int n) { struct rpi_cmd *a; unsigned int newmax; - if (n > 0x100000) { + if (n > CMD_BUFFER_SIZE_MAX) { v4l2_err(&de->ctx->dev->v4l2_dev, "%s: n %u implausible\n", __func__, n); return -ENOMEM; @@ -256,15 +255,14 @@ static int cmds_check_space(struct hevc_d_dec_env *const de, unsigned int n) de->cmd_max, newmax); return -ENOMEM; } - v4l2_info(&de->ctx->dev->v4l2_dev, - "cmd buffer realloc from %u to %u\n", de->cmd_max, newmax); + hevc_d_dbg(1, &de->ctx->dev->v4l2_dev, + "cmd buffer realloc from %u to %u\n", de->cmd_max, newmax); de->cmd_fifo = a; de->cmd_max = newmax; return 0; } -// ???? u16 addr - put in u32 static void p1_apb_write(struct hevc_d_dec_env *const de, const u16 addr, const u32 data) { @@ -506,7 +504,7 @@ static void write_prob(struct hevc_d_dec_env *const de, s->sh->slice_type != HEVC_SLICE_I) ? s->sh->slice_type + 1 : 2 - s->sh->slice_type; - const int q = clip_int(s->slice_qp, 0, 51); + const int q = clamp((int)s->slice_qp, 0, 51); const u8 *p = prob_init[init_type]; u8 dst[RPI_PROB_ARRAY_SIZE]; unsigned int i; @@ -560,21 +558,20 @@ static inline __u32 dma_to_axi_addr(dma_addr_t a) static int write_bitstream(struct hevc_d_dec_env *const de, const struct hevc_d_dec_state *const s) { - // FIXME!!!! - // Note that FFmpeg V4L2 does not remove emulation prevention bytes, - // so this is matched in the configuration here. - // Whether that is the correct behaviour or not is not clear in the - // spec. + /* V4L2 always has emulation prevention bytes in the stream */ const int rpi_use_emu = 1; unsigned int offset = s->sh->data_byte_offset; - const unsigned int len = (s->sh->bit_size + 7) / 8 - offset; + /* BFNUM includes the byte with rbsp_stop_one_bit which is not part + * of slice_segment_data + */ + const unsigned int len = s->sh->bit_size / 8 + 1; dma_addr_t addr = s->src_addr + offset; offset = addr & 63; p1_apb_write(de, RPI_BFBASE, dma_to_axi_addr(addr)); p1_apb_write(de, RPI_BFNUM, len); - p1_apb_write(de, RPI_BFCONTROL, offset + (1 << 7)); // Stop + p1_apb_write(de, RPI_BFCONTROL, offset + (1 << 7)); /* Stop */ p1_apb_write(de, RPI_BFCONTROL, offset + (rpi_use_emu << 6)); return 0; } @@ -698,7 +695,10 @@ static void program_slicecmds(struct hevc_d_dec_env *const de, p1_apb_write(de, 0x4000 + 4 * i, de->slice_msgs[i] & 0xffff); } -/* NoBackwardPredictionFlag 8.3.5 - Simply checks POCs */ +/* NoBackwardPredictionFlag 8.3.5 - Simply checks POCs of the frames referenced + * by the idx array against cur_poc. Needs to be called twice (with L0 & L1) to + * get NoBackwardPredictionFlag. + */ static int has_backward(const struct v4l2_hevc_dpb_entry *const dpb, const __u8 *const idx, const unsigned int n, const s32 cur_poc) @@ -1106,7 +1106,7 @@ static int tile_entry_fill(struct hevc_d_dec_env *const de, 2 | (last_x << 5) | (last_y << 18)); p1_apb_write(de, RPI_TRANSFER, PROB_RELOAD); - // Inc tile + /* Inc tile */ if (++t_x >= s->tile_width) { t_x = 0; ++t_y; @@ -1796,22 +1796,19 @@ void hevc_d_h265_setup(struct hevc_d_ctx *ctx, struct hevc_d_run *run) /* Pre calc parameters */ s->dec = dec; + s->idx_inuse = 0; for (i = 0; i != run->h265.slice_ents; ++i) { const struct v4l2_ctrl_hevc_slice_params *const sh = sh0 + i; const bool last_slice = i + 1 == run->h265.slice_ents; + u32 last_offset = sh->data_byte_offset + DIV_ROUND_UP(sh->bit_size, 8); + unsigned int j; s->sh = sh; - if (run->src->planes[0].bytesused < (sh->bit_size + 7) / 8) { - v4l2_warn(&dev->v4l2_dev, - "Bit size %d > bytesused %d\n", - sh->bit_size, run->src->planes[0].bytesused); - goto fail; - } - if (sh->data_byte_offset >= sh->bit_size / 8) { + if (run->src->planes[0].bytesused < last_offset) { v4l2_warn(&dev->v4l2_dev, - "Bit size %u < Byte offset %u * 8\n", - sh->bit_size, sh->data_byte_offset); + "Last byte offset %d > bytesused %d\n", + last_offset, run->src->planes[0].bytesused); goto fail; } @@ -1830,6 +1827,11 @@ void hevc_d_h265_setup(struct hevc_d_ctx *ctx, struct hevc_d_run *run) 0 : sh->num_ref_idx_l1_active_minus1 + 1; + for (j = 0; j != s->nb_refs[0]; ++j) + s->idx_inuse |= 1 << sh->ref_idx_l0[j]; + for (j = 0; j != s->nb_refs[1]; ++j) + s->idx_inuse |= 1 << sh->ref_idx_l1[j]; + if (s->sps.flags & V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED) populate_scaling_factors(run, de, s); @@ -1860,7 +1862,6 @@ void hevc_d_h265_setup(struct hevc_d_ctx *ctx, struct hevc_d_run *run) * Locate ref frames * At least in the current implementation this is constant across all * slices. If this changes we will need idx mapping code. - * Uses sh so here rather than trigger */ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, @@ -1878,9 +1879,14 @@ void hevc_d_h265_setup(struct hevc_d_ctx *ctx, struct hevc_d_run *run) struct vb2_buffer *buf = vb2_find_buffer(vq, dec->dpb[i].timestamp); if (!buf) { - v4l2_warn(&dev->v4l2_dev, - "Missing DPB ent %d, timestamp=%lld\n", - i, (long long)dec->dpb[i].timestamp); + if (!(s->idx_inuse & (1 << i))) + hevc_d_dbg(2, &dev->v4l2_dev, + "Missing unused DPB ent %d, timestamp=%lld\n", + i, (long long)dec->dpb[i].timestamp); + else + v4l2_warn(&dev->v4l2_dev, + "Missing inuse DPB ent %d, timestamp=%lld\n", + i, (long long)dec->dpb[i].timestamp); continue; } @@ -1959,7 +1965,7 @@ void hevc_d_h265_setup(struct hevc_d_ctx *ctx, struct hevc_d_run *run) fail: if (de) - // Actual error reporting happens in Trigger + /* Actual error reporting happens in Trigger */ de->state = HEVC_D_DECODE_ERROR_DONE; } @@ -2028,11 +2034,17 @@ static void phase2_claimed(struct hevc_d_dev *const dev, void *v) apb_write_vc_len(dev, RPI_OUTCSTRIDE, de->chroma_stride); for (i = 0; i < 16; i++) { - // Strides are in fact unused but fill in anyway - apb_write_vc_addr(dev, 0x9000 + 16 * i, de->ref_addrs[i][0]); - apb_write_vc_len(dev, 0x9004 + 16 * i, de->luma_stride); - apb_write_vc_addr(dev, 0x9008 + 16 * i, de->ref_addrs[i][1]); - apb_write_vc_len(dev, 0x900C + 16 * i, de->chroma_stride); + /* Strides are in fact unused but fill in anyway */ + unsigned int roff = i * RPI_REFREGS_SIZE; + + apb_write_vc_addr(dev, RPI_REFYBASE0 + roff, + de->ref_addrs[i][0]); + apb_write_vc_len(dev, RPI_REFYSTRIDE0 + roff, + de->luma_stride); + apb_write_vc_addr(dev, RPI_REFCBASE0 + roff, + de->ref_addrs[i][1]); + apb_write_vc_len(dev, RPI_REFCSTRIDE0 + roff, + de->chroma_stride); } apb_write(dev, RPI_CONFIG2, de->rpi_config2); @@ -2058,7 +2070,7 @@ static void phase1_claimed(struct hevc_d_dev *const dev, void *v); /* release any and all objects associated with de and reenable phase 1 if * required - */// 1 if required + */ static void phase1_err_fin(struct hevc_d_dev *const dev, struct hevc_d_ctx *const ctx, struct hevc_d_dec_env *const de) @@ -2100,8 +2112,8 @@ static void phase1_thread(struct hevc_d_dev *const dev, void *v) __func__, pu_gptr->size); goto fail; } - v4l2_info(&dev->v4l2_dev, "%s: PU realloc (%zx) OK\n", - __func__, pu_gptr->size); + hevc_d_dbg(1, &dev->v4l2_dev, "%s: PU realloc (%zx) OK\n", + __func__, pu_gptr->size); } if (de->p1_status & STATUS_COEFF_EXHAUSTED) { @@ -2112,8 +2124,8 @@ static void phase1_thread(struct hevc_d_dev *const dev, void *v) __func__, coeff_gptr->size); goto fail; } - v4l2_info(&dev->v4l2_dev, "%s: Coeff realloc (%zx) OK\n", - __func__, coeff_gptr->size); + hevc_d_dbg(1, &dev->v4l2_dev, "%s: Coeff realloc (%zx) OK\n", + __func__, coeff_gptr->size); } phase1_claimed(dev, de); @@ -2138,8 +2150,8 @@ static void phase1_cb(struct hevc_d_dev *const dev, void *v) de->p1_status = check_status(dev); if (de->p1_status != 0) { - v4l2_info(&dev->v4l2_dev, "%s: Post wait: %#x\n", - __func__, de->p1_status); + hevc_d_dbg(2, &dev->v4l2_dev, "%s: Post wait: %#x\n", + __func__, de->p1_status); if (de->p1_status < 0) goto fail; diff --git a/drivers/media/platform/raspberrypi/hevc_dec/hevc_d_hw.h b/drivers/media/platform/raspberrypi/hevc_dec/hevc_d_hw.h index 8d91931aadf207..e573d3149cff07 100644 --- a/drivers/media/platform/raspberrypi/hevc_dec/hevc_d_hw.h +++ b/drivers/media/platform/raspberrypi/hevc_dec/hevc_d_hw.h @@ -73,6 +73,17 @@ struct hevc_d_hw_irq_ent { #define RPI_COLSTRIDE 0x803C #define RPI_CURRPOC 0x8040 +/* + * Reference frame register values + * There are 16 of these arranged sequentially + */ +#define RPI_REFYBASE0 0x9000 +#define RPI_REFYSTRIDE0 0x9004 +#define RPI_REFCBASE0 0x9008 +#define RPI_REFCSTRIDE0 0x900c +/* Offset to get from REFYBASEn to REFYBASEn+1 */ +#define RPI_REFREGS_SIZE 16 + /* * Write a general register value * Order is unimportant diff --git a/drivers/media/platform/raspberrypi/hevc_dec/hevc_d_video.c b/drivers/media/platform/raspberrypi/hevc_dec/hevc_d_video.c index 274af191d9e65e..f02c238711c4e7 100644 --- a/drivers/media/platform/raspberrypi/hevc_dec/hevc_d_video.c +++ b/drivers/media/platform/raspberrypi/hevc_dec/hevc_d_video.c @@ -284,8 +284,8 @@ static u32 pixelformat_from_sps(const struct v4l2_ctrl_hevc_sps * const sps, const int index) { static const u32 all_formats[] = { - //V4L2_PIX_FMT_NV12MT_COL128, - //V4L2_PIX_FMT_NV12MT_10_COL128, + V4L2_PIX_FMT_NV12MT_COL128, + V4L2_PIX_FMT_NV12MT_10_COL128, V4L2_PIX_FMT_NV12_COL128, V4L2_PIX_FMT_NV12_10_COL128, }; @@ -298,12 +298,11 @@ static u32 pixelformat_from_sps(const struct v4l2_ctrl_hevc_sps * const sps, pf = all_formats[index]; } else { if (index == 0) { -/* if (sps->bit_depth_luma_minus8 == 0) + if (sps->bit_depth_luma_minus8 == 0) pf = V4L2_PIX_FMT_NV12MT_COL128; else if (sps->bit_depth_luma_minus8 == 2) pf = V4L2_PIX_FMT_NV12MT_10_COL128; } else if (index == 1) { - */ if (sps->bit_depth_luma_minus8 == 0) pf = V4L2_PIX_FMT_NV12_COL128; else if (sps->bit_depth_luma_minus8 == 2) @@ -597,14 +596,13 @@ static int hevc_d_buf_prepare(struct vb2_buffer *vb) return 0; } -/* Only stops the clock if streaom off on both output & capture */ +/* + * Stop the clock for this context + * clk_disable_unprepare does ref counting so this will not actually + * disable the clock if there are other running contexts + */ static void stop_clock(struct hevc_d_dev *dev, struct hevc_d_ctx *ctx) { - if (ctx->src_stream_on || - ctx->dst_stream_on) - return; - - clk_set_min_rate(dev->clock, 0); clk_disable_unprepare(dev->clock); } @@ -634,29 +632,18 @@ static int hevc_d_start_streaming(struct vb2_queue *vq, unsigned int count) struct hevc_d_dev *dev = ctx->dev; int ret = 0; - if (!V4L2_TYPE_IS_OUTPUT(vq->type)) { - ctx->dst_stream_on = 1; - goto ok; - } - - if (ctx->src_fmt.pixelformat != V4L2_PIX_FMT_HEVC_SLICE) { - ret = -EINVAL; - goto fail_cleanup; - } - - if (ctx->src_stream_on) - goto ok; + v4l2_m2m_update_start_streaming_state(ctx->fh.m2m_ctx, vq); - ret = start_clock(dev, ctx); - if (ret) - goto fail_cleanup; + if (V4L2_TYPE_IS_OUTPUT(vq->type)) { + ret = start_clock(dev, ctx); + if (ret) + goto fail_cleanup; - ret = hevc_d_h265_start(ctx); - if (ret) - goto fail_stop_clock; + ret = hevc_d_h265_start(ctx); + if (ret) + goto fail_stop_clock; + } - ctx->src_stream_on = 1; -ok: return 0; fail_stop_clock: @@ -673,17 +660,15 @@ static void hevc_d_stop_streaming(struct vb2_queue *vq) struct hevc_d_dev *dev = ctx->dev; if (V4L2_TYPE_IS_OUTPUT(vq->type)) { - ctx->src_stream_on = 0; hevc_d_h265_stop(ctx); - } else { - ctx->dst_stream_on = 0; + stop_clock(dev, ctx); } hevc_d_queue_cleanup(vq, VB2_BUF_STATE_ERROR); vb2_wait_for_all_buffers(vq); - stop_clock(dev, ctx); + v4l2_m2m_update_stop_streaming_state(ctx->fh.m2m_ctx, vq); } static void hevc_d_buf_queue(struct vb2_buffer *vb) @@ -721,6 +706,7 @@ int hevc_d_queue_init(void *priv, struct vb2_queue *src_vq, src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; src_vq->io_modes = VB2_MMAP | VB2_DMABUF; + src_vq->dma_attrs = DMA_ATTR_NO_KERNEL_MAPPING; src_vq->drv_priv = ctx; src_vq->buf_struct_size = sizeof(struct hevc_d_buffer); src_vq->ops = &hevc_d_qops; @@ -737,6 +723,7 @@ int hevc_d_queue_init(void *priv, struct vb2_queue *src_vq, dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; + dst_vq->dma_attrs = DMA_ATTR_NO_KERNEL_MAPPING; dst_vq->drv_priv = ctx; dst_vq->buf_struct_size = sizeof(struct hevc_d_buffer); dst_vq->min_queued_buffers = 1;