1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-only */ 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * Copyright (c) 2013 Texas Instruments Inc. 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * David Griego, <dagriego@biglakesoftware.com> 6*4882a593Smuzhiyun * Dale Farnsworth, <dale@farnsworth.org> 7*4882a593Smuzhiyun * Archit Taneja, <archit@ti.com> 8*4882a593Smuzhiyun */ 9*4882a593Smuzhiyun 10*4882a593Smuzhiyun #ifndef __TI_VPDMA_H_ 11*4882a593Smuzhiyun #define __TI_VPDMA_H_ 12*4882a593Smuzhiyun 13*4882a593Smuzhiyun #define VPDMA_MAX_NUM_LIST 8 14*4882a593Smuzhiyun /* 15*4882a593Smuzhiyun * A vpdma_buf tracks the size, DMA address and mapping status of each 16*4882a593Smuzhiyun * driver DMA area. 17*4882a593Smuzhiyun */ 18*4882a593Smuzhiyun struct vpdma_buf { 19*4882a593Smuzhiyun void *addr; 20*4882a593Smuzhiyun dma_addr_t dma_addr; 21*4882a593Smuzhiyun size_t size; 22*4882a593Smuzhiyun bool mapped; 23*4882a593Smuzhiyun }; 24*4882a593Smuzhiyun 25*4882a593Smuzhiyun struct vpdma_desc_list { 26*4882a593Smuzhiyun struct vpdma_buf buf; 27*4882a593Smuzhiyun void *next; 28*4882a593Smuzhiyun int type; 29*4882a593Smuzhiyun }; 30*4882a593Smuzhiyun 31*4882a593Smuzhiyun struct vpdma_data { 32*4882a593Smuzhiyun void __iomem *base; 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun struct platform_device *pdev; 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun spinlock_t lock; 37*4882a593Smuzhiyun bool hwlist_used[VPDMA_MAX_NUM_LIST]; 38*4882a593Smuzhiyun void *hwlist_priv[VPDMA_MAX_NUM_LIST]; 39*4882a593Smuzhiyun /* callback to VPE driver when the firmware is loaded */ 40*4882a593Smuzhiyun void (*cb)(struct platform_device *pdev); 41*4882a593Smuzhiyun }; 42*4882a593Smuzhiyun 43*4882a593Smuzhiyun enum vpdma_data_format_type { 44*4882a593Smuzhiyun VPDMA_DATA_FMT_TYPE_YUV, 45*4882a593Smuzhiyun VPDMA_DATA_FMT_TYPE_RGB, 46*4882a593Smuzhiyun VPDMA_DATA_FMT_TYPE_MISC, 47*4882a593Smuzhiyun }; 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun struct vpdma_data_format { 50*4882a593Smuzhiyun enum vpdma_data_format_type type; 51*4882a593Smuzhiyun int data_type; 52*4882a593Smuzhiyun u8 depth; 53*4882a593Smuzhiyun }; 54*4882a593Smuzhiyun 55*4882a593Smuzhiyun #define VPDMA_DESC_ALIGN 16 /* 16-byte descriptor alignment */ 56*4882a593Smuzhiyun #define VPDMA_STRIDE_ALIGN 16 /* 57*4882a593Smuzhiyun * line stride of source and dest 58*4882a593Smuzhiyun * buffers should be 16 byte aligned 59*4882a593Smuzhiyun */ 60*4882a593Smuzhiyun #define VPDMA_MAX_STRIDE 65520 /* Max line stride 16 byte aligned */ 61*4882a593Smuzhiyun #define VPDMA_DTD_DESC_SIZE 32 /* 8 words */ 62*4882a593Smuzhiyun #define VPDMA_CFD_CTD_DESC_SIZE 16 /* 4 words */ 63*4882a593Smuzhiyun 64*4882a593Smuzhiyun #define VPDMA_LIST_TYPE_NORMAL 0 65*4882a593Smuzhiyun #define VPDMA_LIST_TYPE_SELF_MODIFYING 1 66*4882a593Smuzhiyun #define VPDMA_LIST_TYPE_DOORBELL 2 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun enum vpdma_yuv_formats { 69*4882a593Smuzhiyun VPDMA_DATA_FMT_Y444 = 0, 70*4882a593Smuzhiyun VPDMA_DATA_FMT_Y422, 71*4882a593Smuzhiyun VPDMA_DATA_FMT_Y420, 72*4882a593Smuzhiyun VPDMA_DATA_FMT_C444, 73*4882a593Smuzhiyun VPDMA_DATA_FMT_C422, 74*4882a593Smuzhiyun VPDMA_DATA_FMT_C420, 75*4882a593Smuzhiyun VPDMA_DATA_FMT_CB420, 76*4882a593Smuzhiyun VPDMA_DATA_FMT_YCR422, 77*4882a593Smuzhiyun VPDMA_DATA_FMT_YC444, 78*4882a593Smuzhiyun VPDMA_DATA_FMT_CRY422, 79*4882a593Smuzhiyun VPDMA_DATA_FMT_CBY422, 80*4882a593Smuzhiyun VPDMA_DATA_FMT_YCB422, 81*4882a593Smuzhiyun }; 82*4882a593Smuzhiyun 83*4882a593Smuzhiyun enum vpdma_rgb_formats { 84*4882a593Smuzhiyun VPDMA_DATA_FMT_RGB565 = 0, 85*4882a593Smuzhiyun VPDMA_DATA_FMT_ARGB16_1555, 86*4882a593Smuzhiyun VPDMA_DATA_FMT_ARGB16, 87*4882a593Smuzhiyun VPDMA_DATA_FMT_RGBA16_5551, 88*4882a593Smuzhiyun VPDMA_DATA_FMT_RGBA16, 89*4882a593Smuzhiyun VPDMA_DATA_FMT_ARGB24, 90*4882a593Smuzhiyun VPDMA_DATA_FMT_RGB24, 91*4882a593Smuzhiyun VPDMA_DATA_FMT_ARGB32, 92*4882a593Smuzhiyun VPDMA_DATA_FMT_RGBA24, 93*4882a593Smuzhiyun VPDMA_DATA_FMT_RGBA32, 94*4882a593Smuzhiyun VPDMA_DATA_FMT_BGR565, 95*4882a593Smuzhiyun VPDMA_DATA_FMT_ABGR16_1555, 96*4882a593Smuzhiyun VPDMA_DATA_FMT_ABGR16, 97*4882a593Smuzhiyun VPDMA_DATA_FMT_BGRA16_5551, 98*4882a593Smuzhiyun VPDMA_DATA_FMT_BGRA16, 99*4882a593Smuzhiyun VPDMA_DATA_FMT_ABGR24, 100*4882a593Smuzhiyun VPDMA_DATA_FMT_BGR24, 101*4882a593Smuzhiyun VPDMA_DATA_FMT_ABGR32, 102*4882a593Smuzhiyun VPDMA_DATA_FMT_BGRA24, 103*4882a593Smuzhiyun VPDMA_DATA_FMT_BGRA32, 104*4882a593Smuzhiyun }; 105*4882a593Smuzhiyun 106*4882a593Smuzhiyun enum vpdma_raw_formats { 107*4882a593Smuzhiyun VPDMA_DATA_FMT_RAW8 = 0, 108*4882a593Smuzhiyun VPDMA_DATA_FMT_RAW16, 109*4882a593Smuzhiyun }; 110*4882a593Smuzhiyun 111*4882a593Smuzhiyun enum vpdma_misc_formats { 112*4882a593Smuzhiyun VPDMA_DATA_FMT_MV = 0, 113*4882a593Smuzhiyun }; 114*4882a593Smuzhiyun 115*4882a593Smuzhiyun extern const struct vpdma_data_format vpdma_yuv_fmts[]; 116*4882a593Smuzhiyun extern const struct vpdma_data_format vpdma_rgb_fmts[]; 117*4882a593Smuzhiyun extern const struct vpdma_data_format vpdma_raw_fmts[]; 118*4882a593Smuzhiyun extern const struct vpdma_data_format vpdma_misc_fmts[]; 119*4882a593Smuzhiyun 120*4882a593Smuzhiyun enum vpdma_frame_start_event { 121*4882a593Smuzhiyun VPDMA_FSEVENT_HDMI_FID = 0, 122*4882a593Smuzhiyun VPDMA_FSEVENT_DVO2_FID, 123*4882a593Smuzhiyun VPDMA_FSEVENT_HDCOMP_FID, 124*4882a593Smuzhiyun VPDMA_FSEVENT_SD_FID, 125*4882a593Smuzhiyun VPDMA_FSEVENT_LM_FID0, 126*4882a593Smuzhiyun VPDMA_FSEVENT_LM_FID1, 127*4882a593Smuzhiyun VPDMA_FSEVENT_LM_FID2, 128*4882a593Smuzhiyun VPDMA_FSEVENT_CHANNEL_ACTIVE, 129*4882a593Smuzhiyun }; 130*4882a593Smuzhiyun 131*4882a593Smuzhiyun /* max width configurations */ 132*4882a593Smuzhiyun enum vpdma_max_width { 133*4882a593Smuzhiyun MAX_OUT_WIDTH_UNLIMITED = 0, 134*4882a593Smuzhiyun MAX_OUT_WIDTH_REG1, 135*4882a593Smuzhiyun MAX_OUT_WIDTH_REG2, 136*4882a593Smuzhiyun MAX_OUT_WIDTH_REG3, 137*4882a593Smuzhiyun MAX_OUT_WIDTH_352, 138*4882a593Smuzhiyun MAX_OUT_WIDTH_768, 139*4882a593Smuzhiyun MAX_OUT_WIDTH_1280, 140*4882a593Smuzhiyun MAX_OUT_WIDTH_1920, 141*4882a593Smuzhiyun }; 142*4882a593Smuzhiyun 143*4882a593Smuzhiyun /* max height configurations */ 144*4882a593Smuzhiyun enum vpdma_max_height { 145*4882a593Smuzhiyun MAX_OUT_HEIGHT_UNLIMITED = 0, 146*4882a593Smuzhiyun MAX_OUT_HEIGHT_REG1, 147*4882a593Smuzhiyun MAX_OUT_HEIGHT_REG2, 148*4882a593Smuzhiyun MAX_OUT_HEIGHT_REG3, 149*4882a593Smuzhiyun MAX_OUT_HEIGHT_288, 150*4882a593Smuzhiyun MAX_OUT_HEIGHT_576, 151*4882a593Smuzhiyun MAX_OUT_HEIGHT_720, 152*4882a593Smuzhiyun MAX_OUT_HEIGHT_1080, 153*4882a593Smuzhiyun }; 154*4882a593Smuzhiyun 155*4882a593Smuzhiyun /* 156*4882a593Smuzhiyun * VPDMA channel numbers 157*4882a593Smuzhiyun */ 158*4882a593Smuzhiyun enum vpdma_channel { 159*4882a593Smuzhiyun VPE_CHAN_LUMA1_IN, 160*4882a593Smuzhiyun VPE_CHAN_CHROMA1_IN, 161*4882a593Smuzhiyun VPE_CHAN_LUMA2_IN, 162*4882a593Smuzhiyun VPE_CHAN_CHROMA2_IN, 163*4882a593Smuzhiyun VPE_CHAN_LUMA3_IN, 164*4882a593Smuzhiyun VPE_CHAN_CHROMA3_IN, 165*4882a593Smuzhiyun VPE_CHAN_MV_IN, 166*4882a593Smuzhiyun VPE_CHAN_MV_OUT, 167*4882a593Smuzhiyun VPE_CHAN_LUMA_OUT, 168*4882a593Smuzhiyun VPE_CHAN_CHROMA_OUT, 169*4882a593Smuzhiyun VPE_CHAN_RGB_OUT, 170*4882a593Smuzhiyun }; 171*4882a593Smuzhiyun 172*4882a593Smuzhiyun #define VIP_CHAN_VIP2_OFFSET 70 173*4882a593Smuzhiyun #define VIP_CHAN_MULT_PORTB_OFFSET 16 174*4882a593Smuzhiyun #define VIP_CHAN_YUV_PORTB_OFFSET 2 175*4882a593Smuzhiyun #define VIP_CHAN_RGB_PORTB_OFFSET 1 176*4882a593Smuzhiyun 177*4882a593Smuzhiyun #define VPDMA_MAX_CHANNELS 256 178*4882a593Smuzhiyun 179*4882a593Smuzhiyun /* flags for VPDMA data descriptors */ 180*4882a593Smuzhiyun #define VPDMA_DATA_ODD_LINE_SKIP (1 << 0) 181*4882a593Smuzhiyun #define VPDMA_DATA_EVEN_LINE_SKIP (1 << 1) 182*4882a593Smuzhiyun #define VPDMA_DATA_FRAME_1D (1 << 2) 183*4882a593Smuzhiyun #define VPDMA_DATA_MODE_TILED (1 << 3) 184*4882a593Smuzhiyun 185*4882a593Smuzhiyun /* 186*4882a593Smuzhiyun * client identifiers used for configuration descriptors 187*4882a593Smuzhiyun */ 188*4882a593Smuzhiyun #define CFD_MMR_CLIENT 0 189*4882a593Smuzhiyun #define CFD_SC_CLIENT 4 190*4882a593Smuzhiyun 191*4882a593Smuzhiyun /* Address data block header format */ 192*4882a593Smuzhiyun struct vpdma_adb_hdr { 193*4882a593Smuzhiyun u32 offset; 194*4882a593Smuzhiyun u32 nwords; 195*4882a593Smuzhiyun u32 reserved0; 196*4882a593Smuzhiyun u32 reserved1; 197*4882a593Smuzhiyun }; 198*4882a593Smuzhiyun 199*4882a593Smuzhiyun /* helpers for creating ADB headers for config descriptors MMRs as client */ 200*4882a593Smuzhiyun #define ADB_ADDR(dma_buf, str, fld) ((dma_buf)->addr + offsetof(str, fld)) 201*4882a593Smuzhiyun #define MMR_ADB_ADDR(buf, str, fld) ADB_ADDR(&(buf), struct str, fld) 202*4882a593Smuzhiyun 203*4882a593Smuzhiyun #define VPDMA_SET_MMR_ADB_HDR(buf, str, hdr, regs, offset_a) \ 204*4882a593Smuzhiyun do { \ 205*4882a593Smuzhiyun struct vpdma_adb_hdr *h; \ 206*4882a593Smuzhiyun struct str *adb = NULL; \ 207*4882a593Smuzhiyun h = MMR_ADB_ADDR(buf, str, hdr); \ 208*4882a593Smuzhiyun h->offset = (offset_a); \ 209*4882a593Smuzhiyun h->nwords = sizeof(adb->regs) >> 2; \ 210*4882a593Smuzhiyun } while (0) 211*4882a593Smuzhiyun 212*4882a593Smuzhiyun /* vpdma descriptor buffer allocation and management */ 213*4882a593Smuzhiyun int vpdma_alloc_desc_buf(struct vpdma_buf *buf, size_t size); 214*4882a593Smuzhiyun void vpdma_free_desc_buf(struct vpdma_buf *buf); 215*4882a593Smuzhiyun int vpdma_map_desc_buf(struct vpdma_data *vpdma, struct vpdma_buf *buf); 216*4882a593Smuzhiyun void vpdma_unmap_desc_buf(struct vpdma_data *vpdma, struct vpdma_buf *buf); 217*4882a593Smuzhiyun 218*4882a593Smuzhiyun /* vpdma descriptor list funcs */ 219*4882a593Smuzhiyun int vpdma_create_desc_list(struct vpdma_desc_list *list, size_t size, int type); 220*4882a593Smuzhiyun void vpdma_reset_desc_list(struct vpdma_desc_list *list); 221*4882a593Smuzhiyun void vpdma_free_desc_list(struct vpdma_desc_list *list); 222*4882a593Smuzhiyun int vpdma_submit_descs(struct vpdma_data *vpdma, struct vpdma_desc_list *list, 223*4882a593Smuzhiyun int list_num); 224*4882a593Smuzhiyun bool vpdma_list_busy(struct vpdma_data *vpdma, int list_num); 225*4882a593Smuzhiyun void vpdma_update_dma_addr(struct vpdma_data *vpdma, 226*4882a593Smuzhiyun struct vpdma_desc_list *list, dma_addr_t dma_addr, 227*4882a593Smuzhiyun void *write_dtd, int drop, int idx); 228*4882a593Smuzhiyun 229*4882a593Smuzhiyun /* VPDMA hardware list funcs */ 230*4882a593Smuzhiyun int vpdma_hwlist_alloc(struct vpdma_data *vpdma, void *priv); 231*4882a593Smuzhiyun void *vpdma_hwlist_get_priv(struct vpdma_data *vpdma, int list_num); 232*4882a593Smuzhiyun void *vpdma_hwlist_release(struct vpdma_data *vpdma, int list_num); 233*4882a593Smuzhiyun 234*4882a593Smuzhiyun /* helpers for creating vpdma descriptors */ 235*4882a593Smuzhiyun void vpdma_add_cfd_block(struct vpdma_desc_list *list, int client, 236*4882a593Smuzhiyun struct vpdma_buf *blk, u32 dest_offset); 237*4882a593Smuzhiyun void vpdma_add_cfd_adb(struct vpdma_desc_list *list, int client, 238*4882a593Smuzhiyun struct vpdma_buf *adb); 239*4882a593Smuzhiyun void vpdma_add_sync_on_channel_ctd(struct vpdma_desc_list *list, 240*4882a593Smuzhiyun enum vpdma_channel chan); 241*4882a593Smuzhiyun void vpdma_add_abort_channel_ctd(struct vpdma_desc_list *list, 242*4882a593Smuzhiyun int chan_num); 243*4882a593Smuzhiyun void vpdma_add_out_dtd(struct vpdma_desc_list *list, int width, 244*4882a593Smuzhiyun int stride, const struct v4l2_rect *c_rect, 245*4882a593Smuzhiyun const struct vpdma_data_format *fmt, dma_addr_t dma_addr, 246*4882a593Smuzhiyun int max_w, int max_h, enum vpdma_channel chan, u32 flags); 247*4882a593Smuzhiyun void vpdma_rawchan_add_out_dtd(struct vpdma_desc_list *list, int width, 248*4882a593Smuzhiyun int stride, const struct v4l2_rect *c_rect, 249*4882a593Smuzhiyun const struct vpdma_data_format *fmt, dma_addr_t dma_addr, 250*4882a593Smuzhiyun int max_w, int max_h, int raw_vpdma_chan, u32 flags); 251*4882a593Smuzhiyun 252*4882a593Smuzhiyun void vpdma_add_in_dtd(struct vpdma_desc_list *list, int width, 253*4882a593Smuzhiyun int stride, const struct v4l2_rect *c_rect, 254*4882a593Smuzhiyun const struct vpdma_data_format *fmt, dma_addr_t dma_addr, 255*4882a593Smuzhiyun enum vpdma_channel chan, int field, u32 flags, int frame_width, 256*4882a593Smuzhiyun int frame_height, int start_h, int start_v); 257*4882a593Smuzhiyun int vpdma_list_cleanup(struct vpdma_data *vpdma, int list_num, 258*4882a593Smuzhiyun int *channels, int size); 259*4882a593Smuzhiyun 260*4882a593Smuzhiyun /* vpdma list interrupt management */ 261*4882a593Smuzhiyun void vpdma_enable_list_complete_irq(struct vpdma_data *vpdma, int irq_num, 262*4882a593Smuzhiyun int list_num, bool enable); 263*4882a593Smuzhiyun void vpdma_clear_list_stat(struct vpdma_data *vpdma, int irq_num, 264*4882a593Smuzhiyun int list_num); 265*4882a593Smuzhiyun unsigned int vpdma_get_list_stat(struct vpdma_data *vpdma, int irq_num); 266*4882a593Smuzhiyun unsigned int vpdma_get_list_mask(struct vpdma_data *vpdma, int irq_num); 267*4882a593Smuzhiyun 268*4882a593Smuzhiyun /* vpdma client configuration */ 269*4882a593Smuzhiyun void vpdma_set_line_mode(struct vpdma_data *vpdma, int line_mode, 270*4882a593Smuzhiyun enum vpdma_channel chan); 271*4882a593Smuzhiyun void vpdma_set_frame_start_event(struct vpdma_data *vpdma, 272*4882a593Smuzhiyun enum vpdma_frame_start_event fs_event, enum vpdma_channel chan); 273*4882a593Smuzhiyun void vpdma_set_max_size(struct vpdma_data *vpdma, int reg_addr, 274*4882a593Smuzhiyun u32 width, u32 height); 275*4882a593Smuzhiyun 276*4882a593Smuzhiyun void vpdma_set_bg_color(struct vpdma_data *vpdma, 277*4882a593Smuzhiyun struct vpdma_data_format *fmt, u32 color); 278*4882a593Smuzhiyun void vpdma_dump_regs(struct vpdma_data *vpdma); 279*4882a593Smuzhiyun 280*4882a593Smuzhiyun /* initialize vpdma, passed with VPE's platform device pointer */ 281*4882a593Smuzhiyun int vpdma_create(struct platform_device *pdev, struct vpdma_data *vpdma, 282*4882a593Smuzhiyun void (*cb)(struct platform_device *pdev)); 283*4882a593Smuzhiyun 284*4882a593Smuzhiyun #endif 285