1/* 2 * VPDMA helper library 3 * 4 * Copyright (c) 2013 Texas Instruments Inc. 5 * 6 * David Griego, <dagriego@biglakesoftware.com> 7 * Dale Farnsworth, <dale@farnsworth.org> 8 * Archit Taneja, <archit@ti.com> 9 * 10 * This program is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License version 2 as published by 12 * the Free Software Foundation. 13 */ 14 15#include <linux/delay.h> 16#include <linux/dma-mapping.h> 17#include <linux/err.h> 18#include <linux/firmware.h> 19#include <linux/io.h> 20#include <linux/module.h> 21#include <linux/platform_device.h> 22#include <linux/sched.h> 23#include <linux/slab.h> 24#include <linux/videodev2.h> 25 26#include "vpdma.h" 27#include "vpdma_priv.h" 28 29#define VPDMA_FIRMWARE "vpdma-1b8.bin" 30 31const struct vpdma_data_format vpdma_yuv_fmts[] = { 32 [VPDMA_DATA_FMT_Y444] = { 33 .type = VPDMA_DATA_FMT_TYPE_YUV, 34 .data_type = DATA_TYPE_Y444, 35 .depth = 8, 36 }, 37 [VPDMA_DATA_FMT_Y422] = { 38 .type = VPDMA_DATA_FMT_TYPE_YUV, 39 .data_type = DATA_TYPE_Y422, 40 .depth = 8, 41 }, 42 [VPDMA_DATA_FMT_Y420] = { 43 .type = VPDMA_DATA_FMT_TYPE_YUV, 44 .data_type = DATA_TYPE_Y420, 45 .depth = 8, 46 }, 47 [VPDMA_DATA_FMT_C444] = { 48 .type = VPDMA_DATA_FMT_TYPE_YUV, 49 .data_type = DATA_TYPE_C444, 50 .depth = 8, 51 }, 52 [VPDMA_DATA_FMT_C422] = { 53 .type = VPDMA_DATA_FMT_TYPE_YUV, 54 .data_type = DATA_TYPE_C422, 55 .depth = 8, 56 }, 57 [VPDMA_DATA_FMT_C420] = { 58 .type = VPDMA_DATA_FMT_TYPE_YUV, 59 .data_type = DATA_TYPE_C420, 60 .depth = 4, 61 }, 62 [VPDMA_DATA_FMT_YC422] = { 63 .type = VPDMA_DATA_FMT_TYPE_YUV, 64 .data_type = DATA_TYPE_YC422, 65 .depth = 16, 66 }, 67 [VPDMA_DATA_FMT_YC444] = { 68 .type = VPDMA_DATA_FMT_TYPE_YUV, 69 .data_type = DATA_TYPE_YC444, 70 .depth = 24, 71 }, 72 [VPDMA_DATA_FMT_CY422] = { 73 .type = VPDMA_DATA_FMT_TYPE_YUV, 74 .data_type = DATA_TYPE_CY422, 75 .depth = 16, 76 }, 77}; 78 79const struct vpdma_data_format vpdma_rgb_fmts[] = { 80 [VPDMA_DATA_FMT_RGB565] = { 81 .type = VPDMA_DATA_FMT_TYPE_RGB, 82 .data_type = DATA_TYPE_RGB16_565, 83 .depth = 16, 84 }, 85 [VPDMA_DATA_FMT_ARGB16_1555] = { 86 .type = VPDMA_DATA_FMT_TYPE_RGB, 87 .data_type = DATA_TYPE_ARGB_1555, 88 .depth = 16, 89 }, 90 [VPDMA_DATA_FMT_ARGB16] = { 91 .type = VPDMA_DATA_FMT_TYPE_RGB, 92 .data_type = DATA_TYPE_ARGB_4444, 93 .depth = 16, 94 }, 95 [VPDMA_DATA_FMT_RGBA16_5551] = { 96 .type = VPDMA_DATA_FMT_TYPE_RGB, 97 .data_type = DATA_TYPE_RGBA_5551, 98 .depth = 16, 99 }, 100 [VPDMA_DATA_FMT_RGBA16] = { 101 .type = VPDMA_DATA_FMT_TYPE_RGB, 102 .data_type = DATA_TYPE_RGBA_4444, 103 .depth = 16, 104 }, 105 [VPDMA_DATA_FMT_ARGB24] = { 106 .type = VPDMA_DATA_FMT_TYPE_RGB, 107 .data_type = DATA_TYPE_ARGB24_6666, 108 .depth = 24, 109 }, 110 [VPDMA_DATA_FMT_RGB24] = { 111 .type = VPDMA_DATA_FMT_TYPE_RGB, 112 .data_type = DATA_TYPE_RGB24_888, 113 .depth = 24, 114 }, 115 [VPDMA_DATA_FMT_ARGB32] = { 116 .type = VPDMA_DATA_FMT_TYPE_RGB, 117 .data_type = DATA_TYPE_ARGB32_8888, 118 .depth = 32, 119 }, 120 [VPDMA_DATA_FMT_RGBA24] = { 121 .type = VPDMA_DATA_FMT_TYPE_RGB, 122 .data_type = DATA_TYPE_RGBA24_6666, 123 .depth = 24, 124 }, 125 [VPDMA_DATA_FMT_RGBA32] = { 126 .type = VPDMA_DATA_FMT_TYPE_RGB, 127 .data_type = DATA_TYPE_RGBA32_8888, 128 .depth = 32, 129 }, 130 [VPDMA_DATA_FMT_BGR565] = { 131 .type = VPDMA_DATA_FMT_TYPE_RGB, 132 .data_type = DATA_TYPE_BGR16_565, 133 .depth = 16, 134 }, 135 [VPDMA_DATA_FMT_ABGR16_1555] = { 136 .type = VPDMA_DATA_FMT_TYPE_RGB, 137 .data_type = DATA_TYPE_ABGR_1555, 138 .depth = 16, 139 }, 140 [VPDMA_DATA_FMT_ABGR16] = { 141 .type = VPDMA_DATA_FMT_TYPE_RGB, 142 .data_type = DATA_TYPE_ABGR_4444, 143 .depth = 16, 144 }, 145 [VPDMA_DATA_FMT_BGRA16_5551] = { 146 .type = VPDMA_DATA_FMT_TYPE_RGB, 147 .data_type = DATA_TYPE_BGRA_5551, 148 .depth = 16, 149 }, 150 [VPDMA_DATA_FMT_BGRA16] = { 151 .type = VPDMA_DATA_FMT_TYPE_RGB, 152 .data_type = DATA_TYPE_BGRA_4444, 153 .depth = 16, 154 }, 155 [VPDMA_DATA_FMT_ABGR24] = { 156 .type = VPDMA_DATA_FMT_TYPE_RGB, 157 .data_type = DATA_TYPE_ABGR24_6666, 158 .depth = 24, 159 }, 160 [VPDMA_DATA_FMT_BGR24] = { 161 .type = VPDMA_DATA_FMT_TYPE_RGB, 162 .data_type = DATA_TYPE_BGR24_888, 163 .depth = 24, 164 }, 165 [VPDMA_DATA_FMT_ABGR32] = { 166 .type = VPDMA_DATA_FMT_TYPE_RGB, 167 .data_type = DATA_TYPE_ABGR32_8888, 168 .depth = 32, 169 }, 170 [VPDMA_DATA_FMT_BGRA24] = { 171 .type = VPDMA_DATA_FMT_TYPE_RGB, 172 .data_type = DATA_TYPE_BGRA24_6666, 173 .depth = 24, 174 }, 175 [VPDMA_DATA_FMT_BGRA32] = { 176 .type = VPDMA_DATA_FMT_TYPE_RGB, 177 .data_type = DATA_TYPE_BGRA32_8888, 178 .depth = 32, 179 }, 180}; 181 182const struct vpdma_data_format vpdma_misc_fmts[] = { 183 [VPDMA_DATA_FMT_MV] = { 184 .type = VPDMA_DATA_FMT_TYPE_MISC, 185 .data_type = DATA_TYPE_MV, 186 .depth = 4, 187 }, 188}; 189 190struct vpdma_channel_info { 191 int num; /* VPDMA channel number */ 192 int cstat_offset; /* client CSTAT register offset */ 193}; 194 195static const struct vpdma_channel_info chan_info[] = { 196 [VPE_CHAN_LUMA1_IN] = { 197 .num = VPE_CHAN_NUM_LUMA1_IN, 198 .cstat_offset = VPDMA_DEI_LUMA1_CSTAT, 199 }, 200 [VPE_CHAN_CHROMA1_IN] = { 201 .num = VPE_CHAN_NUM_CHROMA1_IN, 202 .cstat_offset = VPDMA_DEI_CHROMA1_CSTAT, 203 }, 204 [VPE_CHAN_LUMA2_IN] = { 205 .num = VPE_CHAN_NUM_LUMA2_IN, 206 .cstat_offset = VPDMA_DEI_LUMA2_CSTAT, 207 }, 208 [VPE_CHAN_CHROMA2_IN] = { 209 .num = VPE_CHAN_NUM_CHROMA2_IN, 210 .cstat_offset = VPDMA_DEI_CHROMA2_CSTAT, 211 }, 212 [VPE_CHAN_LUMA3_IN] = { 213 .num = VPE_CHAN_NUM_LUMA3_IN, 214 .cstat_offset = VPDMA_DEI_LUMA3_CSTAT, 215 }, 216 [VPE_CHAN_CHROMA3_IN] = { 217 .num = VPE_CHAN_NUM_CHROMA3_IN, 218 .cstat_offset = VPDMA_DEI_CHROMA3_CSTAT, 219 }, 220 [VPE_CHAN_MV_IN] = { 221 .num = VPE_CHAN_NUM_MV_IN, 222 .cstat_offset = VPDMA_DEI_MV_IN_CSTAT, 223 }, 224 [VPE_CHAN_MV_OUT] = { 225 .num = VPE_CHAN_NUM_MV_OUT, 226 .cstat_offset = VPDMA_DEI_MV_OUT_CSTAT, 227 }, 228 [VPE_CHAN_LUMA_OUT] = { 229 .num = VPE_CHAN_NUM_LUMA_OUT, 230 .cstat_offset = VPDMA_VIP_UP_Y_CSTAT, 231 }, 232 [VPE_CHAN_CHROMA_OUT] = { 233 .num = VPE_CHAN_NUM_CHROMA_OUT, 234 .cstat_offset = VPDMA_VIP_UP_UV_CSTAT, 235 }, 236 [VPE_CHAN_RGB_OUT] = { 237 .num = VPE_CHAN_NUM_RGB_OUT, 238 .cstat_offset = VPDMA_VIP_UP_Y_CSTAT, 239 }, 240}; 241 242static u32 read_reg(struct vpdma_data *vpdma, int offset) 243{ 244 return ioread32(vpdma->base + offset); 245} 246 247static void write_reg(struct vpdma_data *vpdma, int offset, u32 value) 248{ 249 iowrite32(value, vpdma->base + offset); 250} 251 252static int read_field_reg(struct vpdma_data *vpdma, int offset, 253 u32 mask, int shift) 254{ 255 return (read_reg(vpdma, offset) & (mask << shift)) >> shift; 256} 257 258static void write_field_reg(struct vpdma_data *vpdma, int offset, u32 field, 259 u32 mask, int shift) 260{ 261 u32 val = read_reg(vpdma, offset); 262 263 val &= ~(mask << shift); 264 val |= (field & mask) << shift; 265 266 write_reg(vpdma, offset, val); 267} 268 269void vpdma_dump_regs(struct vpdma_data *vpdma) 270{ 271 struct device *dev = &vpdma->pdev->dev; 272 273#define DUMPREG(r) dev_dbg(dev, "%-35s %08x\n", #r, read_reg(vpdma, VPDMA_##r)) 274 275 dev_dbg(dev, "VPDMA Registers:\n"); 276 277 DUMPREG(PID); 278 DUMPREG(LIST_ADDR); 279 DUMPREG(LIST_ATTR); 280 DUMPREG(LIST_STAT_SYNC); 281 DUMPREG(BG_RGB); 282 DUMPREG(BG_YUV); 283 DUMPREG(SETUP); 284 DUMPREG(MAX_SIZE1); 285 DUMPREG(MAX_SIZE2); 286 DUMPREG(MAX_SIZE3); 287 288 /* 289 * dumping registers of only group0 and group3, because VPE channels 290 * lie within group0 and group3 registers 291 */ 292 DUMPREG(INT_CHAN_STAT(0)); 293 DUMPREG(INT_CHAN_MASK(0)); 294 DUMPREG(INT_CHAN_STAT(3)); 295 DUMPREG(INT_CHAN_MASK(3)); 296 DUMPREG(INT_CLIENT0_STAT); 297 DUMPREG(INT_CLIENT0_MASK); 298 DUMPREG(INT_CLIENT1_STAT); 299 DUMPREG(INT_CLIENT1_MASK); 300 DUMPREG(INT_LIST0_STAT); 301 DUMPREG(INT_LIST0_MASK); 302 303 /* 304 * these are registers specific to VPE clients, we can make this 305 * function dump client registers specific to VPE or VIP based on 306 * who is using it 307 */ 308 DUMPREG(DEI_CHROMA1_CSTAT); 309 DUMPREG(DEI_LUMA1_CSTAT); 310 DUMPREG(DEI_CHROMA2_CSTAT); 311 DUMPREG(DEI_LUMA2_CSTAT); 312 DUMPREG(DEI_CHROMA3_CSTAT); 313 DUMPREG(DEI_LUMA3_CSTAT); 314 DUMPREG(DEI_MV_IN_CSTAT); 315 DUMPREG(DEI_MV_OUT_CSTAT); 316 DUMPREG(VIP_UP_Y_CSTAT); 317 DUMPREG(VIP_UP_UV_CSTAT); 318 DUMPREG(VPI_CTL_CSTAT); 319} 320 321/* 322 * Allocate a DMA buffer 323 */ 324int vpdma_alloc_desc_buf(struct vpdma_buf *buf, size_t size) 325{ 326 buf->size = size; 327 buf->mapped = false; 328 buf->addr = kzalloc(size, GFP_KERNEL); 329 if (!buf->addr) 330 return -ENOMEM; 331 332 WARN_ON(((unsigned long)buf->addr & VPDMA_DESC_ALIGN) != 0); 333 334 return 0; 335} 336 337void vpdma_free_desc_buf(struct vpdma_buf *buf) 338{ 339 WARN_ON(buf->mapped); 340 kfree(buf->addr); 341 buf->addr = NULL; 342 buf->size = 0; 343} 344 345/* 346 * map descriptor/payload DMA buffer, enabling DMA access 347 */ 348int vpdma_map_desc_buf(struct vpdma_data *vpdma, struct vpdma_buf *buf) 349{ 350 struct device *dev = &vpdma->pdev->dev; 351 352 WARN_ON(buf->mapped); 353 buf->dma_addr = dma_map_single(dev, buf->addr, buf->size, 354 DMA_TO_DEVICE); 355 if (dma_mapping_error(dev, buf->dma_addr)) { 356 dev_err(dev, "failed to map buffer\n"); 357 return -EINVAL; 358 } 359 360 buf->mapped = true; 361 362 return 0; 363} 364 365/* 366 * unmap descriptor/payload DMA buffer, disabling DMA access and 367 * allowing the main processor to acces the data 368 */ 369void vpdma_unmap_desc_buf(struct vpdma_data *vpdma, struct vpdma_buf *buf) 370{ 371 struct device *dev = &vpdma->pdev->dev; 372 373 if (buf->mapped) 374 dma_unmap_single(dev, buf->dma_addr, buf->size, DMA_TO_DEVICE); 375 376 buf->mapped = false; 377} 378 379/* 380 * create a descriptor list, the user of this list will append configuration, 381 * control and data descriptors to this list, this list will be submitted to 382 * VPDMA. VPDMA's list parser will go through each descriptor and perform the 383 * required DMA operations 384 */ 385int vpdma_create_desc_list(struct vpdma_desc_list *list, size_t size, int type) 386{ 387 int r; 388 389 r = vpdma_alloc_desc_buf(&list->buf, size); 390 if (r) 391 return r; 392 393 list->next = list->buf.addr; 394 395 list->type = type; 396 397 return 0; 398} 399 400/* 401 * once a descriptor list is parsed by VPDMA, we reset the list by emptying it, 402 * to allow new descriptors to be added to the list. 403 */ 404void vpdma_reset_desc_list(struct vpdma_desc_list *list) 405{ 406 list->next = list->buf.addr; 407} 408 409/* 410 * free the buffer allocated fot the VPDMA descriptor list, this should be 411 * called when the user doesn't want to use VPDMA any more. 412 */ 413void vpdma_free_desc_list(struct vpdma_desc_list *list) 414{ 415 vpdma_free_desc_buf(&list->buf); 416 417 list->next = NULL; 418} 419 420static bool vpdma_list_busy(struct vpdma_data *vpdma, int list_num) 421{ 422 return read_reg(vpdma, VPDMA_LIST_STAT_SYNC) & BIT(list_num + 16); 423} 424 425/* 426 * submit a list of DMA descriptors to the VPE VPDMA, do not wait for completion 427 */ 428int vpdma_submit_descs(struct vpdma_data *vpdma, struct vpdma_desc_list *list) 429{ 430 /* we always use the first list */ 431 int list_num = 0; 432 int list_size; 433 434 if (vpdma_list_busy(vpdma, list_num)) 435 return -EBUSY; 436 437 /* 16-byte granularity */ 438 list_size = (list->next - list->buf.addr) >> 4; 439 440 write_reg(vpdma, VPDMA_LIST_ADDR, (u32) list->buf.dma_addr); 441 442 write_reg(vpdma, VPDMA_LIST_ATTR, 443 (list_num << VPDMA_LIST_NUM_SHFT) | 444 (list->type << VPDMA_LIST_TYPE_SHFT) | 445 list_size); 446 447 return 0; 448} 449 450static void dump_cfd(struct vpdma_cfd *cfd) 451{ 452 int class; 453 454 class = cfd_get_class(cfd); 455 456 pr_debug("config descriptor of payload class: %s\n", 457 class == CFD_CLS_BLOCK ? "simple block" : 458 "address data block"); 459 460 if (class == CFD_CLS_BLOCK) 461 pr_debug("word0: dst_addr_offset = 0x%08x\n", 462 cfd->dest_addr_offset); 463 464 if (class == CFD_CLS_BLOCK) 465 pr_debug("word1: num_data_wrds = %d\n", cfd->block_len); 466 467 pr_debug("word2: payload_addr = 0x%08x\n", cfd->payload_addr); 468 469 pr_debug("word3: pkt_type = %d, direct = %d, class = %d, dest = %d, " 470 "payload_len = %d\n", cfd_get_pkt_type(cfd), 471 cfd_get_direct(cfd), class, cfd_get_dest(cfd), 472 cfd_get_payload_len(cfd)); 473} 474 475/* 476 * append a configuration descriptor to the given descriptor list, where the 477 * payload is in the form of a simple data block specified in the descriptor 478 * header, this is used to upload scaler coefficients to the scaler module 479 */ 480void vpdma_add_cfd_block(struct vpdma_desc_list *list, int client, 481 struct vpdma_buf *blk, u32 dest_offset) 482{ 483 struct vpdma_cfd *cfd; 484 int len = blk->size; 485 486 WARN_ON(blk->dma_addr & VPDMA_DESC_ALIGN); 487 488 cfd = list->next; 489 WARN_ON((void *)(cfd + 1) > (list->buf.addr + list->buf.size)); 490 491 cfd->dest_addr_offset = dest_offset; 492 cfd->block_len = len; 493 cfd->payload_addr = (u32) blk->dma_addr; 494 cfd->ctl_payload_len = cfd_pkt_payload_len(CFD_INDIRECT, CFD_CLS_BLOCK, 495 client, len >> 4); 496 497 list->next = cfd + 1; 498 499 dump_cfd(cfd); 500} 501 502/* 503 * append a configuration descriptor to the given descriptor list, where the 504 * payload is in the address data block format, this is used to a configure a 505 * discontiguous set of MMRs 506 */ 507void vpdma_add_cfd_adb(struct vpdma_desc_list *list, int client, 508 struct vpdma_buf *adb) 509{ 510 struct vpdma_cfd *cfd; 511 unsigned int len = adb->size; 512 513 WARN_ON(len & VPDMA_ADB_SIZE_ALIGN); 514 WARN_ON(adb->dma_addr & VPDMA_DESC_ALIGN); 515 516 cfd = list->next; 517 BUG_ON((void *)(cfd + 1) > (list->buf.addr + list->buf.size)); 518 519 cfd->w0 = 0; 520 cfd->w1 = 0; 521 cfd->payload_addr = (u32) adb->dma_addr; 522 cfd->ctl_payload_len = cfd_pkt_payload_len(CFD_INDIRECT, CFD_CLS_ADB, 523 client, len >> 4); 524 525 list->next = cfd + 1; 526 527 dump_cfd(cfd); 528}; 529 530/* 531 * control descriptor format change based on what type of control descriptor it 532 * is, we only use 'sync on channel' control descriptors for now, so assume it's 533 * that 534 */ 535static void dump_ctd(struct vpdma_ctd *ctd) 536{ 537 pr_debug("control descriptor\n"); 538 539 pr_debug("word3: pkt_type = %d, source = %d, ctl_type = %d\n", 540 ctd_get_pkt_type(ctd), ctd_get_source(ctd), ctd_get_ctl(ctd)); 541} 542 543/* 544 * append a 'sync on channel' type control descriptor to the given descriptor 545 * list, this descriptor stalls the VPDMA list till the time DMA is completed 546 * on the specified channel 547 */ 548void vpdma_add_sync_on_channel_ctd(struct vpdma_desc_list *list, 549 enum vpdma_channel chan) 550{ 551 struct vpdma_ctd *ctd; 552 553 ctd = list->next; 554 WARN_ON((void *)(ctd + 1) > (list->buf.addr + list->buf.size)); 555 556 ctd->w0 = 0; 557 ctd->w1 = 0; 558 ctd->w2 = 0; 559 ctd->type_source_ctl = ctd_type_source_ctl(chan_info[chan].num, 560 CTD_TYPE_SYNC_ON_CHANNEL); 561 562 list->next = ctd + 1; 563 564 dump_ctd(ctd); 565} 566 567static void dump_dtd(struct vpdma_dtd *dtd) 568{ 569 int dir, chan; 570 571 dir = dtd_get_dir(dtd); 572 chan = dtd_get_chan(dtd); 573 574 pr_debug("%s data transfer descriptor for channel %d\n", 575 dir == DTD_DIR_OUT ? "outbound" : "inbound", chan); 576 577 pr_debug("word0: data_type = %d, notify = %d, field = %d, 1D = %d, " 578 "even_ln_skp = %d, odd_ln_skp = %d, line_stride = %d\n", 579 dtd_get_data_type(dtd), dtd_get_notify(dtd), dtd_get_field(dtd), 580 dtd_get_1d(dtd), dtd_get_even_line_skip(dtd), 581 dtd_get_odd_line_skip(dtd), dtd_get_line_stride(dtd)); 582 583 if (dir == DTD_DIR_IN) 584 pr_debug("word1: line_length = %d, xfer_height = %d\n", 585 dtd_get_line_length(dtd), dtd_get_xfer_height(dtd)); 586 587 pr_debug("word2: start_addr = %pad\n", &dtd->start_addr); 588 589 pr_debug("word3: pkt_type = %d, mode = %d, dir = %d, chan = %d, " 590 "pri = %d, next_chan = %d\n", dtd_get_pkt_type(dtd), 591 dtd_get_mode(dtd), dir, chan, dtd_get_priority(dtd), 592 dtd_get_next_chan(dtd)); 593 594 if (dir == DTD_DIR_IN) 595 pr_debug("word4: frame_width = %d, frame_height = %d\n", 596 dtd_get_frame_width(dtd), dtd_get_frame_height(dtd)); 597 else 598 pr_debug("word4: desc_write_addr = 0x%08x, write_desc = %d, " 599 "drp_data = %d, use_desc_reg = %d\n", 600 dtd_get_desc_write_addr(dtd), dtd_get_write_desc(dtd), 601 dtd_get_drop_data(dtd), dtd_get_use_desc(dtd)); 602 603 if (dir == DTD_DIR_IN) 604 pr_debug("word5: hor_start = %d, ver_start = %d\n", 605 dtd_get_h_start(dtd), dtd_get_v_start(dtd)); 606 else 607 pr_debug("word5: max_width %d, max_height %d\n", 608 dtd_get_max_width(dtd), dtd_get_max_height(dtd)); 609 610 pr_debug("word6: client specific attr0 = 0x%08x\n", dtd->client_attr0); 611 pr_debug("word7: client specific attr1 = 0x%08x\n", dtd->client_attr1); 612} 613 614/* 615 * append an outbound data transfer descriptor to the given descriptor list, 616 * this sets up a 'client to memory' VPDMA transfer for the given VPDMA channel 617 * 618 * @list: vpdma desc list to which we add this decriptor 619 * @width: width of the image in pixels in memory 620 * @c_rect: compose params of output image 621 * @fmt: vpdma data format of the buffer 622 * dma_addr: dma address as seen by VPDMA 623 * chan: VPDMA channel 624 * flags: VPDMA flags to configure some descriptor fileds 625 */ 626void vpdma_add_out_dtd(struct vpdma_desc_list *list, int width, 627 const struct v4l2_rect *c_rect, 628 const struct vpdma_data_format *fmt, dma_addr_t dma_addr, 629 enum vpdma_channel chan, u32 flags) 630{ 631 int priority = 0; 632 int field = 0; 633 int notify = 1; 634 int channel, next_chan; 635 struct v4l2_rect rect = *c_rect; 636 int depth = fmt->depth; 637 int stride; 638 struct vpdma_dtd *dtd; 639 640 channel = next_chan = chan_info[chan].num; 641 642 if (fmt->type == VPDMA_DATA_FMT_TYPE_YUV && 643 fmt->data_type == DATA_TYPE_C420) { 644 rect.height >>= 1; 645 rect.top >>= 1; 646 depth = 8; 647 } 648 649 stride = ALIGN((depth * width) >> 3, VPDMA_STRIDE_ALIGN); 650 651 dma_addr += rect.top * stride + (rect.left * depth >> 3); 652 653 dtd = list->next; 654 WARN_ON((void *)(dtd + 1) > (list->buf.addr + list->buf.size)); 655 656 dtd->type_ctl_stride = dtd_type_ctl_stride(fmt->data_type, 657 notify, 658 field, 659 !!(flags & VPDMA_DATA_FRAME_1D), 660 !!(flags & VPDMA_DATA_EVEN_LINE_SKIP), 661 !!(flags & VPDMA_DATA_ODD_LINE_SKIP), 662 stride); 663 dtd->w1 = 0; 664 dtd->start_addr = (u32) dma_addr; 665 dtd->pkt_ctl = dtd_pkt_ctl(!!(flags & VPDMA_DATA_MODE_TILED), 666 DTD_DIR_OUT, channel, priority, next_chan); 667 dtd->desc_write_addr = dtd_desc_write_addr(0, 0, 0, 0); 668 dtd->max_width_height = dtd_max_width_height(MAX_OUT_WIDTH_1920, 669 MAX_OUT_HEIGHT_1080); 670 dtd->client_attr0 = 0; 671 dtd->client_attr1 = 0; 672 673 list->next = dtd + 1; 674 675 dump_dtd(dtd); 676} 677 678/* 679 * append an inbound data transfer descriptor to the given descriptor list, 680 * this sets up a 'memory to client' VPDMA transfer for the given VPDMA channel 681 * 682 * @list: vpdma desc list to which we add this decriptor 683 * @width: width of the image in pixels in memory(not the cropped width) 684 * @c_rect: crop params of input image 685 * @fmt: vpdma data format of the buffer 686 * dma_addr: dma address as seen by VPDMA 687 * chan: VPDMA channel 688 * field: top or bottom field info of the input image 689 * flags: VPDMA flags to configure some descriptor fileds 690 * frame_width/height: the complete width/height of the image presented to the 691 * client (this makes sense when multiple channels are 692 * connected to the same client, forming a larger frame) 693 * start_h, start_v: position where the given channel starts providing pixel 694 * data to the client (makes sense when multiple channels 695 * contribute to the client) 696 */ 697void vpdma_add_in_dtd(struct vpdma_desc_list *list, int width, 698 const struct v4l2_rect *c_rect, 699 const struct vpdma_data_format *fmt, dma_addr_t dma_addr, 700 enum vpdma_channel chan, int field, u32 flags, int frame_width, 701 int frame_height, int start_h, int start_v) 702{ 703 int priority = 0; 704 int notify = 1; 705 int depth = fmt->depth; 706 int channel, next_chan; 707 struct v4l2_rect rect = *c_rect; 708 int stride; 709 struct vpdma_dtd *dtd; 710 711 channel = next_chan = chan_info[chan].num; 712 713 if (fmt->type == VPDMA_DATA_FMT_TYPE_YUV && 714 fmt->data_type == DATA_TYPE_C420) { 715 rect.height >>= 1; 716 rect.top >>= 1; 717 depth = 8; 718 } 719 720 stride = ALIGN((depth * width) >> 3, VPDMA_STRIDE_ALIGN); 721 722 dma_addr += rect.top * stride + (rect.left * depth >> 3); 723 724 dtd = list->next; 725 WARN_ON((void *)(dtd + 1) > (list->buf.addr + list->buf.size)); 726 727 dtd->type_ctl_stride = dtd_type_ctl_stride(fmt->data_type, 728 notify, 729 field, 730 !!(flags & VPDMA_DATA_FRAME_1D), 731 !!(flags & VPDMA_DATA_EVEN_LINE_SKIP), 732 !!(flags & VPDMA_DATA_ODD_LINE_SKIP), 733 stride); 734 735 dtd->xfer_length_height = dtd_xfer_length_height(rect.width, 736 rect.height); 737 dtd->start_addr = (u32) dma_addr; 738 dtd->pkt_ctl = dtd_pkt_ctl(!!(flags & VPDMA_DATA_MODE_TILED), 739 DTD_DIR_IN, channel, priority, next_chan); 740 dtd->frame_width_height = dtd_frame_width_height(frame_width, 741 frame_height); 742 dtd->start_h_v = dtd_start_h_v(start_h, start_v); 743 dtd->client_attr0 = 0; 744 dtd->client_attr1 = 0; 745 746 list->next = dtd + 1; 747 748 dump_dtd(dtd); 749} 750 751/* set or clear the mask for list complete interrupt */ 752void vpdma_enable_list_complete_irq(struct vpdma_data *vpdma, int list_num, 753 bool enable) 754{ 755 u32 val; 756 757 val = read_reg(vpdma, VPDMA_INT_LIST0_MASK); 758 if (enable) 759 val |= (1 << (list_num * 2)); 760 else 761 val &= ~(1 << (list_num * 2)); 762 write_reg(vpdma, VPDMA_INT_LIST0_MASK, val); 763} 764 765/* clear previosuly occured list intterupts in the LIST_STAT register */ 766void vpdma_clear_list_stat(struct vpdma_data *vpdma) 767{ 768 write_reg(vpdma, VPDMA_INT_LIST0_STAT, 769 read_reg(vpdma, VPDMA_INT_LIST0_STAT)); 770} 771 772/* 773 * configures the output mode of the line buffer for the given client, the 774 * line buffer content can either be mirrored(each line repeated twice) or 775 * passed to the client as is 776 */ 777void vpdma_set_line_mode(struct vpdma_data *vpdma, int line_mode, 778 enum vpdma_channel chan) 779{ 780 int client_cstat = chan_info[chan].cstat_offset; 781 782 write_field_reg(vpdma, client_cstat, line_mode, 783 VPDMA_CSTAT_LINE_MODE_MASK, VPDMA_CSTAT_LINE_MODE_SHIFT); 784} 785 786/* 787 * configures the event which should trigger VPDMA transfer for the given 788 * client 789 */ 790void vpdma_set_frame_start_event(struct vpdma_data *vpdma, 791 enum vpdma_frame_start_event fs_event, 792 enum vpdma_channel chan) 793{ 794 int client_cstat = chan_info[chan].cstat_offset; 795 796 write_field_reg(vpdma, client_cstat, fs_event, 797 VPDMA_CSTAT_FRAME_START_MASK, VPDMA_CSTAT_FRAME_START_SHIFT); 798} 799 800static void vpdma_firmware_cb(const struct firmware *f, void *context) 801{ 802 struct vpdma_data *vpdma = context; 803 struct vpdma_buf fw_dma_buf; 804 int i, r; 805 806 dev_dbg(&vpdma->pdev->dev, "firmware callback\n"); 807 808 if (!f || !f->data) { 809 dev_err(&vpdma->pdev->dev, "couldn't get firmware\n"); 810 return; 811 } 812 813 /* already initialized */ 814 if (read_field_reg(vpdma, VPDMA_LIST_ATTR, VPDMA_LIST_RDY_MASK, 815 VPDMA_LIST_RDY_SHFT)) { 816 vpdma->cb(vpdma->pdev); 817 return; 818 } 819 820 r = vpdma_alloc_desc_buf(&fw_dma_buf, f->size); 821 if (r) { 822 dev_err(&vpdma->pdev->dev, 823 "failed to allocate dma buffer for firmware\n"); 824 goto rel_fw; 825 } 826 827 memcpy(fw_dma_buf.addr, f->data, f->size); 828 829 vpdma_map_desc_buf(vpdma, &fw_dma_buf); 830 831 write_reg(vpdma, VPDMA_LIST_ADDR, (u32) fw_dma_buf.dma_addr); 832 833 for (i = 0; i < 100; i++) { /* max 1 second */ 834 msleep_interruptible(10); 835 836 if (read_field_reg(vpdma, VPDMA_LIST_ATTR, VPDMA_LIST_RDY_MASK, 837 VPDMA_LIST_RDY_SHFT)) 838 break; 839 } 840 841 if (i == 100) { 842 dev_err(&vpdma->pdev->dev, "firmware upload failed\n"); 843 goto free_buf; 844 } 845 846 vpdma->cb(vpdma->pdev); 847 848free_buf: 849 vpdma_unmap_desc_buf(vpdma, &fw_dma_buf); 850 851 vpdma_free_desc_buf(&fw_dma_buf); 852rel_fw: 853 release_firmware(f); 854} 855 856static int vpdma_load_firmware(struct vpdma_data *vpdma) 857{ 858 int r; 859 struct device *dev = &vpdma->pdev->dev; 860 861 r = request_firmware_nowait(THIS_MODULE, 1, 862 (const char *) VPDMA_FIRMWARE, dev, GFP_KERNEL, vpdma, 863 vpdma_firmware_cb); 864 if (r) { 865 dev_err(dev, "firmware not available %s\n", VPDMA_FIRMWARE); 866 return r; 867 } else { 868 dev_info(dev, "loading firmware %s\n", VPDMA_FIRMWARE); 869 } 870 871 return 0; 872} 873 874struct vpdma_data *vpdma_create(struct platform_device *pdev, 875 void (*cb)(struct platform_device *pdev)) 876{ 877 struct resource *res; 878 struct vpdma_data *vpdma; 879 int r; 880 881 dev_dbg(&pdev->dev, "vpdma_create\n"); 882 883 vpdma = devm_kzalloc(&pdev->dev, sizeof(*vpdma), GFP_KERNEL); 884 if (!vpdma) { 885 dev_err(&pdev->dev, "couldn't alloc vpdma_dev\n"); 886 return ERR_PTR(-ENOMEM); 887 } 888 889 vpdma->pdev = pdev; 890 vpdma->cb = cb; 891 892 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vpdma"); 893 if (res == NULL) { 894 dev_err(&pdev->dev, "missing platform resources data\n"); 895 return ERR_PTR(-ENODEV); 896 } 897 898 vpdma->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 899 if (!vpdma->base) { 900 dev_err(&pdev->dev, "failed to ioremap\n"); 901 return ERR_PTR(-ENOMEM); 902 } 903 904 r = vpdma_load_firmware(vpdma); 905 if (r) { 906 pr_err("failed to load firmware %s\n", VPDMA_FIRMWARE); 907 return ERR_PTR(r); 908 } 909 910 return vpdma; 911} 912MODULE_FIRMWARE(VPDMA_FIRMWARE); 913