Linux Audio

Check our new training course

Loading...
v5.9
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Sample fifo dma implementation
  4 *
  5 * Copyright (C) 2010 Stefani Seibold <stefani@seibold.net>
 
 
 
  6 */
  7
  8#include <linux/init.h>
  9#include <linux/module.h>
 10#include <linux/kfifo.h>
 11
 12/*
 13 * This module shows how to handle fifo dma operations.
 14 */
 15
 16/* fifo size in elements (bytes) */
 17#define FIFO_SIZE	32
 18
 19static struct kfifo fifo;
 20
 21static int __init example_init(void)
 22{
 23	int			i;
 24	unsigned int		ret;
 25	unsigned int		nents;
 26	struct scatterlist	sg[10];
 27
 28	printk(KERN_INFO "DMA fifo test start\n");
 29
 30	if (kfifo_alloc(&fifo, FIFO_SIZE, GFP_KERNEL)) {
 31		printk(KERN_WARNING "error kfifo_alloc\n");
 32		return -ENOMEM;
 33	}
 34
 35	printk(KERN_INFO "queue size: %u\n", kfifo_size(&fifo));
 36
 37	kfifo_in(&fifo, "test", 4);
 38
 39	for (i = 0; i != 9; i++)
 40		kfifo_put(&fifo, i);
 41
 42	/* kick away first byte */
 43	kfifo_skip(&fifo);
 44
 45	printk(KERN_INFO "queue len: %u\n", kfifo_len(&fifo));
 46
 47	/*
 48	 * Configure the kfifo buffer to receive data from DMA input.
 49	 *
 50	 *  .--------------------------------------.
 51	 *  | 0 | 1 | 2 | ... | 12 | 13 | ... | 31 |
 52	 *  |---|------------------|---------------|
 53	 *   \_/ \________________/ \_____________/
 54	 *    \          \                  \
 55	 *     \          \_allocated data   \
 56	 *      \_*free space*                \_*free space*
 57	 *
 58	 * We need two different SG entries: one for the free space area at the
 59	 * end of the kfifo buffer (19 bytes) and another for the first free
 60	 * byte at the beginning, after the kfifo_skip().
 61	 */
 62	sg_init_table(sg, ARRAY_SIZE(sg));
 63	nents = kfifo_dma_in_prepare(&fifo, sg, ARRAY_SIZE(sg), FIFO_SIZE);
 64	printk(KERN_INFO "DMA sgl entries: %d\n", nents);
 65	if (!nents) {
 66		/* fifo is full and no sgl was created */
 67		printk(KERN_WARNING "error kfifo_dma_in_prepare\n");
 68		return -EIO;
 69	}
 70
 71	/* receive data */
 72	printk(KERN_INFO "scatterlist for receive:\n");
 73	for (i = 0; i < nents; i++) {
 74		printk(KERN_INFO
 75		"sg[%d] -> "
 76		"page %p offset 0x%.8x length 0x%.8x\n",
 77			i, sg_page(&sg[i]), sg[i].offset, sg[i].length);
 78
 79		if (sg_is_last(&sg[i]))
 80			break;
 81	}
 82
 83	/* put here your code to setup and exectute the dma operation */
 84	/* ... */
 85
 86	/* example: zero bytes received */
 87	ret = 0;
 88
 89	/* finish the dma operation and update the received data */
 90	kfifo_dma_in_finish(&fifo, ret);
 91
 92	/* Prepare to transmit data, example: 8 bytes */
 93	nents = kfifo_dma_out_prepare(&fifo, sg, ARRAY_SIZE(sg), 8);
 94	printk(KERN_INFO "DMA sgl entries: %d\n", nents);
 95	if (!nents) {
 96		/* no data was available and no sgl was created */
 97		printk(KERN_WARNING "error kfifo_dma_out_prepare\n");
 98		return -EIO;
 99	}
100
101	printk(KERN_INFO "scatterlist for transmit:\n");
102	for (i = 0; i < nents; i++) {
103		printk(KERN_INFO
104		"sg[%d] -> "
105		"page %p offset 0x%.8x length 0x%.8x\n",
106			i, sg_page(&sg[i]), sg[i].offset, sg[i].length);
107
108		if (sg_is_last(&sg[i]))
109			break;
110	}
111
112	/* put here your code to setup and exectute the dma operation */
113	/* ... */
114
115	/* example: 5 bytes transmitted */
116	ret = 5;
117
118	/* finish the dma operation and update the transmitted data */
119	kfifo_dma_out_finish(&fifo, ret);
120
121	ret = kfifo_len(&fifo);
122	printk(KERN_INFO "queue len: %u\n", kfifo_len(&fifo));
123
124	if (ret != 7) {
125		printk(KERN_WARNING "size mismatch: test failed");
126		return -EIO;
127	}
128	printk(KERN_INFO "test passed\n");
129
130	return 0;
131}
132
133static void __exit example_exit(void)
134{
135	kfifo_free(&fifo);
136}
137
138module_init(example_init);
139module_exit(example_exit);
140MODULE_LICENSE("GPL");
141MODULE_AUTHOR("Stefani Seibold <stefani@seibold.net>");
v3.1
 
  1/*
  2 * Sample fifo dma implementation
  3 *
  4 * Copyright (C) 2010 Stefani Seibold <stefani@seibold.net>
  5 *
  6 * Released under the GPL version 2 only.
  7 *
  8 */
  9
 10#include <linux/init.h>
 11#include <linux/module.h>
 12#include <linux/kfifo.h>
 13
 14/*
 15 * This module shows how to handle fifo dma operations.
 16 */
 17
 18/* fifo size in elements (bytes) */
 19#define FIFO_SIZE	32
 20
 21static struct kfifo fifo;
 22
 23static int __init example_init(void)
 24{
 25	int			i;
 26	unsigned int		ret;
 27	unsigned int		nents;
 28	struct scatterlist	sg[10];
 29
 30	printk(KERN_INFO "DMA fifo test start\n");
 31
 32	if (kfifo_alloc(&fifo, FIFO_SIZE, GFP_KERNEL)) {
 33		printk(KERN_WARNING "error kfifo_alloc\n");
 34		return -ENOMEM;
 35	}
 36
 37	printk(KERN_INFO "queue size: %u\n", kfifo_size(&fifo));
 38
 39	kfifo_in(&fifo, "test", 4);
 40
 41	for (i = 0; i != 9; i++)
 42		kfifo_put(&fifo, &i);
 43
 44	/* kick away first byte */
 45	kfifo_skip(&fifo);
 46
 47	printk(KERN_INFO "queue len: %u\n", kfifo_len(&fifo));
 48
 49	/*
 50	 * Configure the kfifo buffer to receive data from DMA input.
 51	 *
 52	 *  .--------------------------------------.
 53	 *  | 0 | 1 | 2 | ... | 12 | 13 | ... | 31 |
 54	 *  |---|------------------|---------------|
 55	 *   \_/ \________________/ \_____________/
 56	 *    \          \                  \
 57	 *     \          \_allocated data   \
 58	 *      \_*free space*                \_*free space*
 59	 *
 60	 * We need two different SG entries: one for the free space area at the
 61	 * end of the kfifo buffer (19 bytes) and another for the first free
 62	 * byte at the beginning, after the kfifo_skip().
 63	 */
 64	sg_init_table(sg, ARRAY_SIZE(sg));
 65	nents = kfifo_dma_in_prepare(&fifo, sg, ARRAY_SIZE(sg), FIFO_SIZE);
 66	printk(KERN_INFO "DMA sgl entries: %d\n", nents);
 67	if (!nents) {
 68		/* fifo is full and no sgl was created */
 69		printk(KERN_WARNING "error kfifo_dma_in_prepare\n");
 70		return -EIO;
 71	}
 72
 73	/* receive data */
 74	printk(KERN_INFO "scatterlist for receive:\n");
 75	for (i = 0; i < nents; i++) {
 76		printk(KERN_INFO
 77		"sg[%d] -> "
 78		"page_link 0x%.8lx offset 0x%.8x length 0x%.8x\n",
 79			i, sg[i].page_link, sg[i].offset, sg[i].length);
 80
 81		if (sg_is_last(&sg[i]))
 82			break;
 83	}
 84
 85	/* put here your code to setup and exectute the dma operation */
 86	/* ... */
 87
 88	/* example: zero bytes received */
 89	ret = 0;
 90
 91	/* finish the dma operation and update the received data */
 92	kfifo_dma_in_finish(&fifo, ret);
 93
 94	/* Prepare to transmit data, example: 8 bytes */
 95	nents = kfifo_dma_out_prepare(&fifo, sg, ARRAY_SIZE(sg), 8);
 96	printk(KERN_INFO "DMA sgl entries: %d\n", nents);
 97	if (!nents) {
 98		/* no data was available and no sgl was created */
 99		printk(KERN_WARNING "error kfifo_dma_out_prepare\n");
100		return -EIO;
101	}
102
103	printk(KERN_INFO "scatterlist for transmit:\n");
104	for (i = 0; i < nents; i++) {
105		printk(KERN_INFO
106		"sg[%d] -> "
107		"page_link 0x%.8lx offset 0x%.8x length 0x%.8x\n",
108			i, sg[i].page_link, sg[i].offset, sg[i].length);
109
110		if (sg_is_last(&sg[i]))
111			break;
112	}
113
114	/* put here your code to setup and exectute the dma operation */
115	/* ... */
116
117	/* example: 5 bytes transmitted */
118	ret = 5;
119
120	/* finish the dma operation and update the transmitted data */
121	kfifo_dma_out_finish(&fifo, ret);
122
123	ret = kfifo_len(&fifo);
124	printk(KERN_INFO "queue len: %u\n", kfifo_len(&fifo));
125
126	if (ret != 7) {
127		printk(KERN_WARNING "size mismatch: test failed");
128		return -EIO;
129	}
130	printk(KERN_INFO "test passed\n");
131
132	return 0;
133}
134
135static void __exit example_exit(void)
136{
137	kfifo_free(&fifo);
138}
139
140module_init(example_init);
141module_exit(example_exit);
142MODULE_LICENSE("GPL");
143MODULE_AUTHOR("Stefani Seibold <stefani@seibold.net>");