xref: /openbmc/linux/sound/soc/sh/siu_pcm.c (revision 1c5af5cf)
1 /*
2  * siu_pcm.c - ALSA driver for Renesas SH7343, SH7722 SIU peripheral.
3  *
4  * Copyright (C) 2009-2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
5  * Copyright (C) 2006 Carlos Munoz <carlos@kenati.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21 #include <linux/delay.h>
22 #include <linux/dma-mapping.h>
23 #include <linux/dmaengine.h>
24 #include <linux/interrupt.h>
25 #include <linux/module.h>
26 #include <linux/platform_device.h>
27 
28 #include <sound/control.h>
29 #include <sound/core.h>
30 #include <sound/pcm.h>
31 #include <sound/pcm_params.h>
32 #include <sound/soc.h>
33 
34 #include <asm/siu.h>
35 
36 #include "siu.h"
37 
38 #define DRV_NAME "siu-i2s"
39 #define GET_MAX_PERIODS(buf_bytes, period_bytes) \
40 				((buf_bytes) / (period_bytes))
41 #define PERIOD_OFFSET(buf_addr, period_num, period_bytes) \
42 				((buf_addr) + ((period_num) * (period_bytes)))
43 
44 #define RWF_STM_RD		0x01		/* Read in progress */
45 #define RWF_STM_WT		0x02		/* Write in progress */
46 
47 struct siu_port *siu_ports[SIU_PORT_NUM];
48 
49 /* transfersize is number of u32 dma transfers per period */
50 static int siu_pcm_stmwrite_stop(struct siu_port *port_info)
51 {
52 	struct siu_info *info = siu_i2s_data;
53 	u32 __iomem *base = info->reg;
54 	struct siu_stream *siu_stream = &port_info->playback;
55 	u32 stfifo;
56 
57 	if (!siu_stream->rw_flg)
58 		return -EPERM;
59 
60 	/* output FIFO disable */
61 	stfifo = siu_read32(base + SIU_STFIFO);
62 	siu_write32(base + SIU_STFIFO, stfifo & ~0x0c180c18);
63 	pr_debug("%s: STFIFO %x -> %x\n", __func__,
64 		 stfifo, stfifo & ~0x0c180c18);
65 
66 	/* during stmwrite clear */
67 	siu_stream->rw_flg = 0;
68 
69 	return 0;
70 }
71 
72 static int siu_pcm_stmwrite_start(struct siu_port *port_info)
73 {
74 	struct siu_stream *siu_stream = &port_info->playback;
75 
76 	if (siu_stream->rw_flg)
77 		return -EPERM;
78 
79 	/* Current period in buffer */
80 	port_info->playback.cur_period = 0;
81 
82 	/* during stmwrite flag set */
83 	siu_stream->rw_flg = RWF_STM_WT;
84 
85 	/* DMA transfer start */
86 	tasklet_schedule(&siu_stream->tasklet);
87 
88 	return 0;
89 }
90 
91 static void siu_dma_tx_complete(void *arg)
92 {
93 	struct siu_stream *siu_stream = arg;
94 
95 	if (!siu_stream->rw_flg)
96 		return;
97 
98 	/* Update completed period count */
99 	if (++siu_stream->cur_period >=
100 	    GET_MAX_PERIODS(siu_stream->buf_bytes,
101 			    siu_stream->period_bytes))
102 		siu_stream->cur_period = 0;
103 
104 	pr_debug("%s: done period #%d (%u/%u bytes), cookie %d\n",
105 		__func__, siu_stream->cur_period,
106 		siu_stream->cur_period * siu_stream->period_bytes,
107 		siu_stream->buf_bytes, siu_stream->cookie);
108 
109 	tasklet_schedule(&siu_stream->tasklet);
110 
111 	/* Notify alsa: a period is done */
112 	snd_pcm_period_elapsed(siu_stream->substream);
113 }
114 
115 static int siu_pcm_wr_set(struct siu_port *port_info,
116 			  dma_addr_t buff, u32 size)
117 {
118 	struct siu_info *info = siu_i2s_data;
119 	u32 __iomem *base = info->reg;
120 	struct siu_stream *siu_stream = &port_info->playback;
121 	struct snd_pcm_substream *substream = siu_stream->substream;
122 	struct device *dev = substream->pcm->card->dev;
123 	struct dma_async_tx_descriptor *desc;
124 	dma_cookie_t cookie;
125 	struct scatterlist sg;
126 	u32 stfifo;
127 
128 	sg_init_table(&sg, 1);
129 	sg_set_page(&sg, pfn_to_page(PFN_DOWN(buff)),
130 		    size, offset_in_page(buff));
131 	sg_dma_len(&sg) = size;
132 	sg_dma_address(&sg) = buff;
133 
134 	desc = dmaengine_prep_slave_sg(siu_stream->chan,
135 		&sg, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
136 	if (!desc) {
137 		dev_err(dev, "Failed to allocate a dma descriptor\n");
138 		return -ENOMEM;
139 	}
140 
141 	desc->callback = siu_dma_tx_complete;
142 	desc->callback_param = siu_stream;
143 	cookie = dmaengine_submit(desc);
144 	if (cookie < 0) {
145 		dev_err(dev, "Failed to submit a dma transfer\n");
146 		return cookie;
147 	}
148 
149 	siu_stream->tx_desc = desc;
150 	siu_stream->cookie = cookie;
151 
152 	dma_async_issue_pending(siu_stream->chan);
153 
154 	/* only output FIFO enable */
155 	stfifo = siu_read32(base + SIU_STFIFO);
156 	siu_write32(base + SIU_STFIFO, stfifo | (port_info->stfifo & 0x0c180c18));
157 	dev_dbg(dev, "%s: STFIFO %x -> %x\n", __func__,
158 		stfifo, stfifo | (port_info->stfifo & 0x0c180c18));
159 
160 	return 0;
161 }
162 
163 static int siu_pcm_rd_set(struct siu_port *port_info,
164 			  dma_addr_t buff, size_t size)
165 {
166 	struct siu_info *info = siu_i2s_data;
167 	u32 __iomem *base = info->reg;
168 	struct siu_stream *siu_stream = &port_info->capture;
169 	struct snd_pcm_substream *substream = siu_stream->substream;
170 	struct device *dev = substream->pcm->card->dev;
171 	struct dma_async_tx_descriptor *desc;
172 	dma_cookie_t cookie;
173 	struct scatterlist sg;
174 	u32 stfifo;
175 
176 	dev_dbg(dev, "%s: %u@%llx\n", __func__, size, (unsigned long long)buff);
177 
178 	sg_init_table(&sg, 1);
179 	sg_set_page(&sg, pfn_to_page(PFN_DOWN(buff)),
180 		    size, offset_in_page(buff));
181 	sg_dma_len(&sg) = size;
182 	sg_dma_address(&sg) = buff;
183 
184 	desc = dmaengine_prep_slave_sg(siu_stream->chan,
185 		&sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
186 	if (!desc) {
187 		dev_err(dev, "Failed to allocate dma descriptor\n");
188 		return -ENOMEM;
189 	}
190 
191 	desc->callback = siu_dma_tx_complete;
192 	desc->callback_param = siu_stream;
193 	cookie = dmaengine_submit(desc);
194 	if (cookie < 0) {
195 		dev_err(dev, "Failed to submit dma descriptor\n");
196 		return cookie;
197 	}
198 
199 	siu_stream->tx_desc = desc;
200 	siu_stream->cookie = cookie;
201 
202 	dma_async_issue_pending(siu_stream->chan);
203 
204 	/* only input FIFO enable */
205 	stfifo = siu_read32(base + SIU_STFIFO);
206 	siu_write32(base + SIU_STFIFO, siu_read32(base + SIU_STFIFO) |
207 		    (port_info->stfifo & 0x13071307));
208 	dev_dbg(dev, "%s: STFIFO %x -> %x\n", __func__,
209 		stfifo, stfifo | (port_info->stfifo & 0x13071307));
210 
211 	return 0;
212 }
213 
214 static void siu_io_tasklet(unsigned long data)
215 {
216 	struct siu_stream *siu_stream = (struct siu_stream *)data;
217 	struct snd_pcm_substream *substream = siu_stream->substream;
218 	struct device *dev = substream->pcm->card->dev;
219 	struct snd_pcm_runtime *rt = substream->runtime;
220 	struct siu_port *port_info = siu_port_info(substream);
221 
222 	dev_dbg(dev, "%s: flags %x\n", __func__, siu_stream->rw_flg);
223 
224 	if (!siu_stream->rw_flg) {
225 		dev_dbg(dev, "%s: stream inactive\n", __func__);
226 		return;
227 	}
228 
229 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
230 		dma_addr_t buff;
231 		size_t count;
232 		u8 *virt;
233 
234 		buff = (dma_addr_t)PERIOD_OFFSET(rt->dma_addr,
235 						siu_stream->cur_period,
236 						siu_stream->period_bytes);
237 		virt = PERIOD_OFFSET(rt->dma_area,
238 				     siu_stream->cur_period,
239 				     siu_stream->period_bytes);
240 		count = siu_stream->period_bytes;
241 
242 		/* DMA transfer start */
243 		siu_pcm_rd_set(port_info, buff, count);
244 	} else {
245 		siu_pcm_wr_set(port_info,
246 			       (dma_addr_t)PERIOD_OFFSET(rt->dma_addr,
247 						siu_stream->cur_period,
248 						siu_stream->period_bytes),
249 			       siu_stream->period_bytes);
250 	}
251 }
252 
253 /* Capture */
254 static int siu_pcm_stmread_start(struct siu_port *port_info)
255 {
256 	struct siu_stream *siu_stream = &port_info->capture;
257 
258 	if (siu_stream->xfer_cnt > 0x1000000)
259 		return -EINVAL;
260 	if (siu_stream->rw_flg)
261 		return -EPERM;
262 
263 	/* Current period in buffer */
264 	siu_stream->cur_period = 0;
265 
266 	/* during stmread flag set */
267 	siu_stream->rw_flg = RWF_STM_RD;
268 
269 	tasklet_schedule(&siu_stream->tasklet);
270 
271 	return 0;
272 }
273 
274 static int siu_pcm_stmread_stop(struct siu_port *port_info)
275 {
276 	struct siu_info *info = siu_i2s_data;
277 	u32 __iomem *base = info->reg;
278 	struct siu_stream *siu_stream = &port_info->capture;
279 	struct device *dev = siu_stream->substream->pcm->card->dev;
280 	u32 stfifo;
281 
282 	if (!siu_stream->rw_flg)
283 		return -EPERM;
284 
285 	/* input FIFO disable */
286 	stfifo = siu_read32(base + SIU_STFIFO);
287 	siu_write32(base + SIU_STFIFO, stfifo & ~0x13071307);
288 	dev_dbg(dev, "%s: STFIFO %x -> %x\n", __func__,
289 		stfifo, stfifo & ~0x13071307);
290 
291 	/* during stmread flag clear */
292 	siu_stream->rw_flg = 0;
293 
294 	return 0;
295 }
296 
297 static int siu_pcm_hw_params(struct snd_pcm_substream *ss,
298 			     struct snd_pcm_hw_params *hw_params)
299 {
300 	struct siu_info *info = siu_i2s_data;
301 	struct device *dev = ss->pcm->card->dev;
302 	int ret;
303 
304 	dev_dbg(dev, "%s: port=%d\n", __func__, info->port_id);
305 
306 	ret = snd_pcm_lib_malloc_pages(ss, params_buffer_bytes(hw_params));
307 	if (ret < 0)
308 		dev_err(dev, "snd_pcm_lib_malloc_pages() failed\n");
309 
310 	return ret;
311 }
312 
313 static int siu_pcm_hw_free(struct snd_pcm_substream *ss)
314 {
315 	struct siu_info *info = siu_i2s_data;
316 	struct siu_port	*port_info = siu_port_info(ss);
317 	struct device *dev = ss->pcm->card->dev;
318 	struct siu_stream *siu_stream;
319 
320 	if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK)
321 		siu_stream = &port_info->playback;
322 	else
323 		siu_stream = &port_info->capture;
324 
325 	dev_dbg(dev, "%s: port=%d\n", __func__, info->port_id);
326 
327 	return snd_pcm_lib_free_pages(ss);
328 }
329 
330 static bool filter(struct dma_chan *chan, void *slave)
331 {
332 	struct sh_dmae_slave *param = slave;
333 
334 	pr_debug("%s: slave ID %d\n", __func__, param->shdma_slave.slave_id);
335 
336 	chan->private = &param->shdma_slave;
337 	return true;
338 }
339 
340 static int siu_pcm_open(struct snd_pcm_substream *ss)
341 {
342 	/* Playback / Capture */
343 	struct snd_soc_pcm_runtime *rtd = ss->private_data;
344 	struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
345 	struct siu_platform *pdata = component->dev->platform_data;
346 	struct siu_info *info = siu_i2s_data;
347 	struct siu_port *port_info = siu_port_info(ss);
348 	struct siu_stream *siu_stream;
349 	u32 port = info->port_id;
350 	struct device *dev = ss->pcm->card->dev;
351 	dma_cap_mask_t mask;
352 	struct sh_dmae_slave *param;
353 
354 	dma_cap_zero(mask);
355 	dma_cap_set(DMA_SLAVE, mask);
356 
357 	dev_dbg(dev, "%s, port=%d@%p\n", __func__, port, port_info);
358 
359 	if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) {
360 		siu_stream = &port_info->playback;
361 		param = &siu_stream->param;
362 		param->shdma_slave.slave_id = port ? pdata->dma_slave_tx_b :
363 			pdata->dma_slave_tx_a;
364 	} else {
365 		siu_stream = &port_info->capture;
366 		param = &siu_stream->param;
367 		param->shdma_slave.slave_id = port ? pdata->dma_slave_rx_b :
368 			pdata->dma_slave_rx_a;
369 	}
370 
371 	/* Get DMA channel */
372 	siu_stream->chan = dma_request_channel(mask, filter, param);
373 	if (!siu_stream->chan) {
374 		dev_err(dev, "DMA channel allocation failed!\n");
375 		return -EBUSY;
376 	}
377 
378 	siu_stream->substream = ss;
379 
380 	return 0;
381 }
382 
383 static int siu_pcm_close(struct snd_pcm_substream *ss)
384 {
385 	struct siu_info *info = siu_i2s_data;
386 	struct device *dev = ss->pcm->card->dev;
387 	struct siu_port *port_info = siu_port_info(ss);
388 	struct siu_stream *siu_stream;
389 
390 	dev_dbg(dev, "%s: port=%d\n", __func__, info->port_id);
391 
392 	if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK)
393 		siu_stream = &port_info->playback;
394 	else
395 		siu_stream = &port_info->capture;
396 
397 	dma_release_channel(siu_stream->chan);
398 	siu_stream->chan = NULL;
399 
400 	siu_stream->substream = NULL;
401 
402 	return 0;
403 }
404 
405 static int siu_pcm_prepare(struct snd_pcm_substream *ss)
406 {
407 	struct siu_info *info = siu_i2s_data;
408 	struct siu_port *port_info = siu_port_info(ss);
409 	struct device *dev = ss->pcm->card->dev;
410 	struct snd_pcm_runtime 	*rt = ss->runtime;
411 	struct siu_stream *siu_stream;
412 	snd_pcm_sframes_t xfer_cnt;
413 
414 	if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK)
415 		siu_stream = &port_info->playback;
416 	else
417 		siu_stream = &port_info->capture;
418 
419 	rt = siu_stream->substream->runtime;
420 
421 	siu_stream->buf_bytes = snd_pcm_lib_buffer_bytes(ss);
422 	siu_stream->period_bytes = snd_pcm_lib_period_bytes(ss);
423 
424 	dev_dbg(dev, "%s: port=%d, %d channels, period=%u bytes\n", __func__,
425 		info->port_id, rt->channels, siu_stream->period_bytes);
426 
427 	/* We only support buffers that are multiples of the period */
428 	if (siu_stream->buf_bytes % siu_stream->period_bytes) {
429 		dev_err(dev, "%s() - buffer=%d not multiple of period=%d\n",
430 		       __func__, siu_stream->buf_bytes,
431 		       siu_stream->period_bytes);
432 		return -EINVAL;
433 	}
434 
435 	xfer_cnt = bytes_to_frames(rt, siu_stream->period_bytes);
436 	if (!xfer_cnt || xfer_cnt > 0x1000000)
437 		return -EINVAL;
438 
439 	siu_stream->format = rt->format;
440 	siu_stream->xfer_cnt = xfer_cnt;
441 
442 	dev_dbg(dev, "port=%d buf=%lx buf_bytes=%d period_bytes=%d "
443 		"format=%d channels=%d xfer_cnt=%d\n", info->port_id,
444 		(unsigned long)rt->dma_addr, siu_stream->buf_bytes,
445 		siu_stream->period_bytes,
446 		siu_stream->format, rt->channels, (int)xfer_cnt);
447 
448 	return 0;
449 }
450 
451 static int siu_pcm_trigger(struct snd_pcm_substream *ss, int cmd)
452 {
453 	struct siu_info *info = siu_i2s_data;
454 	struct device *dev = ss->pcm->card->dev;
455 	struct siu_port *port_info = siu_port_info(ss);
456 	int ret;
457 
458 	dev_dbg(dev, "%s: port=%d@%p, cmd=%d\n", __func__,
459 		info->port_id, port_info, cmd);
460 
461 	switch (cmd) {
462 	case SNDRV_PCM_TRIGGER_START:
463 		if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK)
464 			ret = siu_pcm_stmwrite_start(port_info);
465 		else
466 			ret = siu_pcm_stmread_start(port_info);
467 
468 		if (ret < 0)
469 			dev_warn(dev, "%s: start failed on port=%d\n",
470 				 __func__, info->port_id);
471 
472 		break;
473 	case SNDRV_PCM_TRIGGER_STOP:
474 		if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK)
475 			siu_pcm_stmwrite_stop(port_info);
476 		else
477 			siu_pcm_stmread_stop(port_info);
478 		ret = 0;
479 
480 		break;
481 	default:
482 		dev_err(dev, "%s() unsupported cmd=%d\n", __func__, cmd);
483 		ret = -EINVAL;
484 	}
485 
486 	return ret;
487 }
488 
489 /*
490  * So far only resolution of one period is supported, subject to extending the
491  * dmangine API
492  */
493 static snd_pcm_uframes_t siu_pcm_pointer_dma(struct snd_pcm_substream *ss)
494 {
495 	struct device *dev = ss->pcm->card->dev;
496 	struct siu_info *info = siu_i2s_data;
497 	u32 __iomem *base = info->reg;
498 	struct siu_port *port_info = siu_port_info(ss);
499 	struct snd_pcm_runtime *rt = ss->runtime;
500 	size_t ptr;
501 	struct siu_stream *siu_stream;
502 
503 	if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK)
504 		siu_stream = &port_info->playback;
505 	else
506 		siu_stream = &port_info->capture;
507 
508 	/*
509 	 * ptr is the offset into the buffer where the dma is currently at. We
510 	 * check if the dma buffer has just wrapped.
511 	 */
512 	ptr = PERIOD_OFFSET(rt->dma_addr,
513 			    siu_stream->cur_period,
514 			    siu_stream->period_bytes) - rt->dma_addr;
515 
516 	dev_dbg(dev,
517 		"%s: port=%d, events %x, FSTS %x, xferred %u/%u, cookie %d\n",
518 		__func__, info->port_id, siu_read32(base + SIU_EVNTC),
519 		siu_read32(base + SIU_SBFSTS), ptr, siu_stream->buf_bytes,
520 		siu_stream->cookie);
521 
522 	if (ptr >= siu_stream->buf_bytes)
523 		ptr = 0;
524 
525 	return bytes_to_frames(ss->runtime, ptr);
526 }
527 
528 static int siu_pcm_new(struct snd_soc_pcm_runtime *rtd)
529 {
530 	/* card->dev == socdev->dev, see snd_soc_new_pcms() */
531 	struct snd_card *card = rtd->card->snd_card;
532 	struct snd_pcm *pcm = rtd->pcm;
533 	struct siu_info *info = siu_i2s_data;
534 	struct platform_device *pdev = to_platform_device(card->dev);
535 	int ret;
536 	int i;
537 
538 	/* pdev->id selects between SIUA and SIUB */
539 	if (pdev->id < 0 || pdev->id >= SIU_PORT_NUM)
540 		return -EINVAL;
541 
542 	info->port_id = pdev->id;
543 
544 	/*
545 	 * While the siu has 2 ports, only one port can be on at a time (only 1
546 	 * SPB). So far all the boards using the siu had only one of the ports
547 	 * wired to a codec. To simplify things, we only register one port with
548 	 * alsa. In case both ports are needed, it should be changed here
549 	 */
550 	for (i = pdev->id; i < pdev->id + 1; i++) {
551 		struct siu_port **port_info = &siu_ports[i];
552 
553 		ret = siu_init_port(i, port_info, card);
554 		if (ret < 0)
555 			return ret;
556 
557 		ret = snd_pcm_lib_preallocate_pages_for_all(pcm,
558 				SNDRV_DMA_TYPE_DEV, NULL,
559 				SIU_BUFFER_BYTES_MAX, SIU_BUFFER_BYTES_MAX);
560 		if (ret < 0) {
561 			dev_err(card->dev,
562 			       "snd_pcm_lib_preallocate_pages_for_all() err=%d",
563 				ret);
564 			goto fail;
565 		}
566 
567 		(*port_info)->pcm = pcm;
568 
569 		/* IO tasklets */
570 		tasklet_init(&(*port_info)->playback.tasklet, siu_io_tasklet,
571 			     (unsigned long)&(*port_info)->playback);
572 		tasklet_init(&(*port_info)->capture.tasklet, siu_io_tasklet,
573 			     (unsigned long)&(*port_info)->capture);
574 	}
575 
576 	dev_info(card->dev, "SuperH SIU driver initialized.\n");
577 	return 0;
578 
579 fail:
580 	siu_free_port(siu_ports[pdev->id]);
581 	dev_err(card->dev, "SIU: failed to initialize.\n");
582 	return ret;
583 }
584 
585 static void siu_pcm_free(struct snd_pcm *pcm)
586 {
587 	struct platform_device *pdev = to_platform_device(pcm->card->dev);
588 	struct siu_port *port_info = siu_ports[pdev->id];
589 
590 	tasklet_kill(&port_info->capture.tasklet);
591 	tasklet_kill(&port_info->playback.tasklet);
592 
593 	siu_free_port(port_info);
594 
595 	dev_dbg(pcm->card->dev, "%s\n", __func__);
596 }
597 
598 static const struct snd_pcm_ops siu_pcm_ops = {
599 	.open		= siu_pcm_open,
600 	.close		= siu_pcm_close,
601 	.ioctl		= snd_pcm_lib_ioctl,
602 	.hw_params	= siu_pcm_hw_params,
603 	.hw_free	= siu_pcm_hw_free,
604 	.prepare	= siu_pcm_prepare,
605 	.trigger	= siu_pcm_trigger,
606 	.pointer	= siu_pcm_pointer_dma,
607 };
608 
609 struct snd_soc_component_driver siu_component = {
610 	.name		= DRV_NAME,
611 	.ops			= &siu_pcm_ops,
612 	.pcm_new	= siu_pcm_new,
613 	.pcm_free	= siu_pcm_free,
614 };
615 EXPORT_SYMBOL_GPL(siu_component);
616