Skip to content

Commit 0cd4582

Browse files
committed
dw-dma: register notifier in dma get instead of dma probe
notifier is unregister in dma put. need to register it in get to make sure we do not lose any notifier. Signed-off-by: Pan Xiuli <xiuli.pan@linux.intel.com>
1 parent 3d44dea commit 0cd4582

File tree

1 file changed

+49
-48
lines changed

1 file changed

+49
-48
lines changed

src/drivers/dw/dma.c

Lines changed: 49 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,51 @@ static void dw_dma_increment_pointer(struct dw_dma_chan_data *chan, int bytes)
126126
(chan->ptr_data.current_ptr - chan->ptr_data.end_ptr);
127127
}
128128

129+
#if !CONFIG_HW_LLI
130+
/* reload using LLI data from DMA IRQ cb */
131+
static inline void dw_dma_chan_reload_lli_cb(void *arg, enum notify_id type,
132+
void *data)
133+
{
134+
struct dma_chan_data *channel = data;
135+
struct dma *dma = channel->dma;
136+
struct dw_dma_chan_data *dw_chan = dma_chan_get_data(channel);
137+
struct dw_lli *lli = dw_chan->lli_current;
138+
139+
/* only need to reload if this is a block transfer */
140+
if (!lli || !lli->llp) {
141+
channel->status = COMP_STATE_PREPARE;
142+
return;
143+
}
144+
145+
/* channel not active */
146+
if (channel->status != COMP_STATE_ACTIVE)
147+
return;
148+
149+
/* channel still transferring previous lli */
150+
if (dma_reg_read(dma, DW_DMA_CHAN_EN) & DW_CHAN(channel->index))
151+
return;
152+
153+
/* get current and next block pointers */
154+
lli = (struct dw_lli *)lli->llp;
155+
dw_chan->lli_current = lli;
156+
157+
/* channel needs to start from scratch, so write SAR and DAR */
158+
dma_reg_write(dma, DW_SAR(channel->index), lli->sar);
159+
dma_reg_write(dma, DW_DAR(channel->index), lli->dar);
160+
161+
/* program CTL_LO and CTL_HI */
162+
dma_reg_write(dma, DW_CTRL_LOW(channel->index), lli->ctrl_lo);
163+
dma_reg_write(dma, DW_CTRL_HIGH(channel->index), lli->ctrl_hi);
164+
165+
/* program CFG_LO and CFG_HI */
166+
dma_reg_write(dma, DW_CFG_LOW(channel->index), dw_chan->cfg_lo);
167+
dma_reg_write(dma, DW_CFG_HIGH(channel->index), dw_chan->cfg_hi);
168+
169+
/* enable the channel */
170+
dma_reg_write(dma, DW_DMA_CHAN_EN, DW_CHAN_UNMASK(channel->index));
171+
}
172+
#endif
173+
129174
/* allocate next free DMA channel */
130175
static struct dma_chan_data *dw_dma_channel_get(struct dma *dma,
131176
unsigned int req_chan)
@@ -148,6 +193,10 @@ static struct dma_chan_data *dw_dma_channel_get(struct dma *dma,
148193
dma->chan[i].status = COMP_STATE_READY;
149194

150195
atomic_add(&dma->num_channels_busy, 1);
196+
#if !CONFIG_HW_LLI
197+
notifier_register(&dma->chan[i], &dma->chan[i],
198+
NOTIFIER_ID_DMA_IRQ, dw_dma_chan_reload_lli_cb);
199+
#endif
151200

152201
/* return channel */
153202
spin_unlock_irq(dma->lock, flags);
@@ -760,50 +809,6 @@ static int dw_dma_pm_context_store(struct dma *dma)
760809
return 0;
761810
}
762811

763-
#if !CONFIG_HW_LLI
764-
/* reload using LLI data from DMA IRQ cb */
765-
static inline void dw_dma_chan_reload_lli_cb(void *arg, enum notify_id type,
766-
void *data)
767-
{
768-
struct dma_chan_data *channel = data;
769-
struct dma *dma = channel->dma;
770-
struct dw_dma_chan_data *dw_chan = dma_chan_get_data(channel);
771-
struct dw_lli *lli = dw_chan->lli_current;
772-
773-
/* only need to reload if this is a block transfer */
774-
if (!lli || !lli->llp) {
775-
channel->status = COMP_STATE_PREPARE;
776-
return;
777-
}
778-
779-
/* channel not active */
780-
if (channel->status != COMP_STATE_ACTIVE)
781-
return;
782-
783-
/* channel still transferring previous lli */
784-
if (dma_reg_read(dma, DW_DMA_CHAN_EN) & DW_CHAN(channel->index))
785-
return;
786-
787-
/* get current and next block pointers */
788-
lli = (struct dw_lli *)lli->llp;
789-
dw_chan->lli_current = lli;
790-
791-
/* channel needs to start from scratch, so write SAR and DAR */
792-
dma_reg_write(dma, DW_SAR(channel->index), lli->sar);
793-
dma_reg_write(dma, DW_DAR(channel->index), lli->dar);
794-
795-
/* program CTL_LO and CTL_HI */
796-
dma_reg_write(dma, DW_CTRL_LOW(channel->index), lli->ctrl_lo);
797-
dma_reg_write(dma, DW_CTRL_HIGH(channel->index), lli->ctrl_hi);
798-
799-
/* program CFG_LO and CFG_HI */
800-
dma_reg_write(dma, DW_CFG_LOW(channel->index), dw_chan->cfg_lo);
801-
dma_reg_write(dma, DW_CFG_HIGH(channel->index), dw_chan->cfg_hi);
802-
803-
/* enable the channel */
804-
dma_reg_write(dma, DW_DMA_CHAN_EN, DW_CHAN_UNMASK(channel->index));
805-
}
806-
#endif
807812

808813
static void dw_dma_verify_transfer(struct dma_chan_data *channel,
809814
struct dma_cb_data *next)
@@ -968,10 +973,6 @@ static int dw_dma_probe(struct dma *dma)
968973
chan->dma = dma;
969974
chan->index = i;
970975
chan->core = DMA_CORE_INVALID;
971-
#if !CONFIG_HW_LLI
972-
notifier_register(chan, chan, NOTIFIER_ID_DMA_IRQ,
973-
dw_dma_chan_reload_lli_cb);
974-
#endif
975976

976977
dw_chan = rzalloc(RZONE_SYS_RUNTIME | RZONE_FLAG_UNCACHED,
977978
SOF_MEM_CAPS_RAM, sizeof(*dw_chan));

0 commit comments

Comments
 (0)