/* Compile params part 1: generate template nodes */ static int fdma_compile1(struct fdma *fdma, struct stm_dma_params *params) { struct stm_dma_params *this; for (this = params; this; this = this->next) { struct fdma_xfer_descriptor *desc = this->priv; if (desc != NULL) continue; desc = kzalloc(sizeof(struct fdma_xfer_descriptor), params->context); if (desc == NULL) return -ENOMEM; this->priv = desc; if (this->mode == MODE_SRC_SCATTER) desc->extrapolate_fn = fdma_extrapolate_sg_src; else if (this->mode == MODE_DST_SCATTER) desc->extrapolate_fn = fdma_extrapolate_sg_dst; else desc->extrapolate_fn = fdma_extrapolate_simple; if (this->mode == MODE_PACED) fdma_setup_paced_node(this, &desc->template_llu); else fdma_setup_freerunning_node(this, &desc->template_llu); /* For any 1D transfers, line_len = nbytes */ desc->extrapolate_line_len = !((DIM_SRC(this->dim) == 2) || (DIM_DST(this->dim) == 2)); } return 0; }
static int fdma_setup_freerunning_node(struct stm_dma_params *params, struct fdma_llu_entry *llu) { memset(llu, 0, sizeof(*llu)); if (params->node_pause) llu->control |= SET_NODE_COMP_PAUSE | SET_NODE_COMP_IRQ; if (params->node_interrupt) llu->control |= SET_NODE_COMP_IRQ; if (DIM_SRC(params->dim) == 0) llu->control |= NODE_ADDR_STATIC << SOURCE_ADDR; else llu->control |= NODE_ADDR_INCR << SOURCE_ADDR; if (DIM_DST(params->dim) == 0) llu->control |= NODE_ADDR_STATIC << DEST_ADDR; else llu->control |= NODE_ADDR_INCR << DEST_ADDR; llu->line_len = params->line_len; llu->sstride = params->sstride; llu->dstride = params->dstride; return 0; }
static int fdma_setup_paced_node(struct stm_dma_params *params, struct fdma_llu_entry *llu) { memset(llu, 0, sizeof(*llu)); /* Moved this into the extrapolate functions so that we can * change channel in the same way as address. Yech */ /* llu->control = params->req_line; */ llu->size_bytes = params->node_bytes; llu->line_len = params->node_bytes; if (params->node_pause) /* In order to recieve the pause interrupt * we must also enable end of node interrupts. */ llu->control |= SET_NODE_COMP_PAUSE | SET_NODE_COMP_IRQ; if (params->node_interrupt) llu->control |= SET_NODE_COMP_IRQ; if (DIM_SRC(params->dim) == 0) llu->control |= NODE_ADDR_STATIC << SOURCE_ADDR; else llu->control |= NODE_ADDR_INCR << SOURCE_ADDR; if (DIM_DST(params->dim) == 0) llu->control |= NODE_ADDR_STATIC << DEST_ADDR; else llu->control |= NODE_ADDR_INCR << DEST_ADDR; return 0; }
static struct fdma_llu_node *fdma_extrapolate_sg_src( struct stm_dma_params *params, struct fdma_xfer_descriptor *desc, struct fdma_llu_node *llu_node) { int i; struct scatterlist *sg = params->srcsg; struct fdma_llu_node *last_llu_node = llu_node; int offset = 0; for (i = 0; i < params->sglen; i++) { struct fdma_llu_entry *dest_llu = llu_node->virt_addr; dest_llu->control = desc->template_llu.control; dest_llu->size_bytes = sg_dma_len(sg); dest_llu->saddr = sg_dma_address(sg); dest_llu->daddr = params->dar + offset; if (desc->extrapolate_line_len) dest_llu->line_len = sg_dma_len(sg); else dest_llu->line_len = desc->template_llu.line_len; dest_llu->sstride = desc->template_llu.sstride; dest_llu->dstride = 0; if (DIM_DST(params->dim) != 0) offset += sg_dma_len(sg); last_llu_node = llu_node++; dest_llu->next_item = llu_node->dma_addr; sg++; } return last_llu_node; }