| .. | .. |
|---|
| 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 | |
|---|