.. | .. |
---|
34 | 34 | unsigned int completion) |
---|
35 | 35 | { |
---|
36 | 36 | struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe); |
---|
37 | | - bool complete = completion == VSP1_DL_FRAME_END_COMPLETED; |
---|
38 | 37 | |
---|
39 | 38 | if (drm_pipe->du_complete) { |
---|
40 | 39 | struct vsp1_entity *uif = drm_pipe->uif; |
---|
| 40 | + unsigned int status = completion |
---|
| 41 | + & (VSP1_DU_STATUS_COMPLETE | |
---|
| 42 | + VSP1_DU_STATUS_WRITEBACK); |
---|
41 | 43 | u32 crc; |
---|
42 | 44 | |
---|
43 | 45 | crc = uif ? vsp1_uif_get_crc(to_uif(&uif->subdev)) : 0; |
---|
44 | | - drm_pipe->du_complete(drm_pipe->du_private, complete, crc); |
---|
| 46 | + drm_pipe->du_complete(drm_pipe->du_private, status, crc); |
---|
45 | 47 | } |
---|
46 | 48 | |
---|
47 | 49 | if (completion & VSP1_DL_FRAME_END_INTERNAL) { |
---|
.. | .. |
---|
333 | 335 | * on the BRx sink pad 0 and propagated inside the entity, not on the |
---|
334 | 336 | * source pad. |
---|
335 | 337 | */ |
---|
336 | | - format.pad = pipe->brx->source_pad; |
---|
| 338 | + format.pad = brx->source_pad; |
---|
337 | 339 | format.format.width = drm_pipe->width; |
---|
338 | 340 | format.format.height = drm_pipe->height; |
---|
339 | 341 | format.format.field = V4L2_FIELD_NONE; |
---|
340 | 342 | |
---|
341 | | - ret = v4l2_subdev_call(&pipe->brx->subdev, pad, set_fmt, NULL, |
---|
| 343 | + ret = v4l2_subdev_call(&brx->subdev, pad, set_fmt, NULL, |
---|
342 | 344 | &format); |
---|
343 | 345 | if (ret < 0) |
---|
344 | 346 | return ret; |
---|
345 | 347 | |
---|
346 | 348 | dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n", |
---|
347 | 349 | __func__, format.format.width, format.format.height, |
---|
348 | | - format.format.code, BRX_NAME(pipe->brx), pipe->brx->source_pad); |
---|
| 350 | + format.format.code, BRX_NAME(brx), brx->source_pad); |
---|
349 | 351 | |
---|
350 | 352 | if (format.format.width != drm_pipe->width || |
---|
351 | 353 | format.format.height != drm_pipe->height) { |
---|
.. | .. |
---|
537 | 539 | struct vsp1_entity *next; |
---|
538 | 540 | struct vsp1_dl_list *dl; |
---|
539 | 541 | struct vsp1_dl_body *dlb; |
---|
| 542 | + unsigned int dl_flags = 0; |
---|
| 543 | + |
---|
| 544 | + if (drm_pipe->force_brx_release) |
---|
| 545 | + dl_flags |= VSP1_DL_FRAME_END_INTERNAL; |
---|
| 546 | + if (pipe->output->writeback) |
---|
| 547 | + dl_flags |= VSP1_DL_FRAME_END_WRITEBACK; |
---|
540 | 548 | |
---|
541 | 549 | dl = vsp1_dl_list_get(pipe->output->dlm); |
---|
542 | 550 | dlb = vsp1_dl_list_get_body0(dl); |
---|
.. | .. |
---|
554 | 562 | } |
---|
555 | 563 | |
---|
556 | 564 | vsp1_entity_route_setup(entity, pipe, dlb); |
---|
557 | | - vsp1_entity_configure_stream(entity, pipe, dlb); |
---|
| 565 | + vsp1_entity_configure_stream(entity, pipe, dl, dlb); |
---|
558 | 566 | vsp1_entity_configure_frame(entity, pipe, dl, dlb); |
---|
559 | 567 | vsp1_entity_configure_partition(entity, pipe, dl, dlb); |
---|
560 | 568 | } |
---|
561 | 569 | |
---|
562 | | - vsp1_dl_list_commit(dl, drm_pipe->force_brx_release); |
---|
| 570 | + vsp1_dl_list_commit(dl, dl_flags); |
---|
| 571 | +} |
---|
| 572 | + |
---|
| 573 | +static int vsp1_du_pipeline_set_rwpf_format(struct vsp1_device *vsp1, |
---|
| 574 | + struct vsp1_rwpf *rwpf, |
---|
| 575 | + u32 pixelformat, unsigned int pitch) |
---|
| 576 | +{ |
---|
| 577 | + const struct vsp1_format_info *fmtinfo; |
---|
| 578 | + unsigned int chroma_hsub; |
---|
| 579 | + |
---|
| 580 | + fmtinfo = vsp1_get_format_info(vsp1, pixelformat); |
---|
| 581 | + if (!fmtinfo) { |
---|
| 582 | + dev_dbg(vsp1->dev, "Unsupported pixel format %08x\n", |
---|
| 583 | + pixelformat); |
---|
| 584 | + return -EINVAL; |
---|
| 585 | + } |
---|
| 586 | + |
---|
| 587 | + /* |
---|
| 588 | + * Only formats with three planes can affect the chroma planes pitch. |
---|
| 589 | + * All formats with two planes have a horizontal subsampling value of 2, |
---|
| 590 | + * but combine U and V in a single chroma plane, which thus results in |
---|
| 591 | + * the luma plane and chroma plane having the same pitch. |
---|
| 592 | + */ |
---|
| 593 | + chroma_hsub = (fmtinfo->planes == 3) ? fmtinfo->hsub : 1; |
---|
| 594 | + |
---|
| 595 | + rwpf->fmtinfo = fmtinfo; |
---|
| 596 | + rwpf->format.num_planes = fmtinfo->planes; |
---|
| 597 | + rwpf->format.plane_fmt[0].bytesperline = pitch; |
---|
| 598 | + rwpf->format.plane_fmt[1].bytesperline = pitch / chroma_hsub; |
---|
| 599 | + |
---|
| 600 | + return 0; |
---|
563 | 601 | } |
---|
564 | 602 | |
---|
565 | 603 | /* ----------------------------------------------------------------------------- |
---|
.. | .. |
---|
700 | 738 | drm_pipe->du_private = cfg->callback_data; |
---|
701 | 739 | |
---|
702 | 740 | /* Disable the display interrupts. */ |
---|
703 | | - vsp1_write(vsp1, VI6_DISP_IRQ_STA, 0); |
---|
704 | | - vsp1_write(vsp1, VI6_DISP_IRQ_ENB, 0); |
---|
| 741 | + vsp1_write(vsp1, VI6_DISP_IRQ_STA(pipe_index), 0); |
---|
| 742 | + vsp1_write(vsp1, VI6_DISP_IRQ_ENB(pipe_index), 0); |
---|
705 | 743 | |
---|
706 | 744 | /* Configure all entities in the pipeline. */ |
---|
707 | 745 | vsp1_du_pipeline_configure(pipe); |
---|
.. | .. |
---|
769 | 807 | { |
---|
770 | 808 | struct vsp1_device *vsp1 = dev_get_drvdata(dev); |
---|
771 | 809 | struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index]; |
---|
772 | | - const struct vsp1_format_info *fmtinfo; |
---|
773 | | - unsigned int chroma_hsub; |
---|
774 | 810 | struct vsp1_rwpf *rpf; |
---|
| 811 | + int ret; |
---|
775 | 812 | |
---|
776 | 813 | if (rpf_index >= vsp1->info->rpf_count) |
---|
777 | 814 | return -EINVAL; |
---|
.. | .. |
---|
804 | 841 | * Store the format, stride, memory buffer address, crop and compose |
---|
805 | 842 | * rectangles and Z-order position and for the input. |
---|
806 | 843 | */ |
---|
807 | | - fmtinfo = vsp1_get_format_info(vsp1, cfg->pixelformat); |
---|
808 | | - if (!fmtinfo) { |
---|
809 | | - dev_dbg(vsp1->dev, "Unsupported pixel format %08x for RPF\n", |
---|
810 | | - cfg->pixelformat); |
---|
811 | | - return -EINVAL; |
---|
812 | | - } |
---|
| 844 | + ret = vsp1_du_pipeline_set_rwpf_format(vsp1, rpf, cfg->pixelformat, |
---|
| 845 | + cfg->pitch); |
---|
| 846 | + if (ret < 0) |
---|
| 847 | + return ret; |
---|
813 | 848 | |
---|
814 | | - /* |
---|
815 | | - * Only formats with three planes can affect the chroma planes pitch. |
---|
816 | | - * All formats with two planes have a horizontal subsampling value of 2, |
---|
817 | | - * but combine U and V in a single chroma plane, which thus results in |
---|
818 | | - * the luma plane and chroma plane having the same pitch. |
---|
819 | | - */ |
---|
820 | | - chroma_hsub = (fmtinfo->planes == 3) ? fmtinfo->hsub : 1; |
---|
821 | | - |
---|
822 | | - rpf->fmtinfo = fmtinfo; |
---|
823 | | - rpf->format.num_planes = fmtinfo->planes; |
---|
824 | | - rpf->format.plane_fmt[0].bytesperline = cfg->pitch; |
---|
825 | | - rpf->format.plane_fmt[1].bytesperline = cfg->pitch / chroma_hsub; |
---|
826 | 849 | rpf->alpha = cfg->alpha; |
---|
827 | 850 | |
---|
828 | 851 | rpf->mem.addr[0] = cfg->mem[0]; |
---|
.. | .. |
---|
851 | 874 | struct vsp1_device *vsp1 = dev_get_drvdata(dev); |
---|
852 | 875 | struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index]; |
---|
853 | 876 | struct vsp1_pipeline *pipe = &drm_pipe->pipe; |
---|
| 877 | + int ret; |
---|
854 | 878 | |
---|
855 | 879 | drm_pipe->crc = cfg->crc; |
---|
856 | 880 | |
---|
857 | 881 | mutex_lock(&vsp1->drm->lock); |
---|
| 882 | + |
---|
| 883 | + if (cfg->writeback.pixelformat) { |
---|
| 884 | + const struct vsp1_du_writeback_config *wb_cfg = &cfg->writeback; |
---|
| 885 | + |
---|
| 886 | + ret = vsp1_du_pipeline_set_rwpf_format(vsp1, pipe->output, |
---|
| 887 | + wb_cfg->pixelformat, |
---|
| 888 | + wb_cfg->pitch); |
---|
| 889 | + if (WARN_ON(ret < 0)) |
---|
| 890 | + goto done; |
---|
| 891 | + |
---|
| 892 | + pipe->output->mem.addr[0] = wb_cfg->mem[0]; |
---|
| 893 | + pipe->output->mem.addr[1] = wb_cfg->mem[1]; |
---|
| 894 | + pipe->output->mem.addr[2] = wb_cfg->mem[2]; |
---|
| 895 | + pipe->output->writeback = true; |
---|
| 896 | + } |
---|
| 897 | + |
---|
858 | 898 | vsp1_du_pipeline_setup_inputs(vsp1, pipe); |
---|
859 | 899 | vsp1_du_pipeline_configure(pipe); |
---|
| 900 | + |
---|
| 901 | +done: |
---|
860 | 902 | mutex_unlock(&vsp1->drm->lock); |
---|
861 | 903 | } |
---|
862 | 904 | EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush); |
---|
.. | .. |
---|
870 | 912 | * skip cache sync. This will need to be revisited when support for |
---|
871 | 913 | * non-coherent buffers will be added to the DU driver. |
---|
872 | 914 | */ |
---|
873 | | - return dma_map_sg_attrs(vsp1->bus_master, sgt->sgl, sgt->nents, |
---|
874 | | - DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); |
---|
| 915 | + return dma_map_sgtable(vsp1->bus_master, sgt, DMA_TO_DEVICE, |
---|
| 916 | + DMA_ATTR_SKIP_CPU_SYNC); |
---|
875 | 917 | } |
---|
876 | 918 | EXPORT_SYMBOL_GPL(vsp1_du_map_sg); |
---|
877 | 919 | |
---|
.. | .. |
---|
879 | 921 | { |
---|
880 | 922 | struct vsp1_device *vsp1 = dev_get_drvdata(dev); |
---|
881 | 923 | |
---|
882 | | - dma_unmap_sg_attrs(vsp1->bus_master, sgt->sgl, sgt->nents, |
---|
883 | | - DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); |
---|
| 924 | + dma_unmap_sgtable(vsp1->bus_master, sgt, DMA_TO_DEVICE, |
---|
| 925 | + DMA_ATTR_SKIP_CPU_SYNC); |
---|
884 | 926 | } |
---|
885 | 927 | EXPORT_SYMBOL_GPL(vsp1_du_unmap_sg); |
---|
886 | 928 | |
---|