diff options
Diffstat (limited to 'sound/soc/intel/sst-haswell-ipc.c')
-rw-r--r-- | sound/soc/intel/sst-haswell-ipc.c | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c index f46bb4ddde6f..e7996b39a484 100644 --- a/sound/soc/intel/sst-haswell-ipc.c +++ b/sound/soc/intel/sst-haswell-ipc.c | |||
@@ -617,7 +617,7 @@ static void hsw_notification_work(struct work_struct *work) | |||
617 | case IPC_POSITION_CHANGED: | 617 | case IPC_POSITION_CHANGED: |
618 | trace_ipc_notification("DSP stream position changed for", | 618 | trace_ipc_notification("DSP stream position changed for", |
619 | stream->reply.stream_hw_id); | 619 | stream->reply.stream_hw_id); |
620 | sst_dsp_inbox_read(hsw->dsp, pos, sizeof(pos)); | 620 | sst_dsp_inbox_read(hsw->dsp, pos, sizeof(*pos)); |
621 | 621 | ||
622 | if (stream->notify_position) | 622 | if (stream->notify_position) |
623 | stream->notify_position(stream, stream->pdata); | 623 | stream->notify_position(stream, stream->pdata); |
@@ -991,7 +991,8 @@ int sst_hsw_stream_get_volume(struct sst_hsw *hsw, struct sst_hsw_stream *stream | |||
991 | return -EINVAL; | 991 | return -EINVAL; |
992 | 992 | ||
993 | sst_dsp_read(hsw->dsp, volume, | 993 | sst_dsp_read(hsw->dsp, volume, |
994 | stream->reply.volume_register_address[channel], sizeof(volume)); | 994 | stream->reply.volume_register_address[channel], |
995 | sizeof(*volume)); | ||
995 | 996 | ||
996 | return 0; | 997 | return 0; |
997 | } | 998 | } |
@@ -1158,11 +1159,14 @@ struct sst_hsw_stream *sst_hsw_stream_new(struct sst_hsw *hsw, int id, | |||
1158 | void *data) | 1159 | void *data) |
1159 | { | 1160 | { |
1160 | struct sst_hsw_stream *stream; | 1161 | struct sst_hsw_stream *stream; |
1162 | struct sst_dsp *sst = hsw->dsp; | ||
1163 | unsigned long flags; | ||
1161 | 1164 | ||
1162 | stream = kzalloc(sizeof(*stream), GFP_KERNEL); | 1165 | stream = kzalloc(sizeof(*stream), GFP_KERNEL); |
1163 | if (stream == NULL) | 1166 | if (stream == NULL) |
1164 | return NULL; | 1167 | return NULL; |
1165 | 1168 | ||
1169 | spin_lock_irqsave(&sst->spinlock, flags); | ||
1166 | list_add(&stream->node, &hsw->stream_list); | 1170 | list_add(&stream->node, &hsw->stream_list); |
1167 | stream->notify_position = notify_position; | 1171 | stream->notify_position = notify_position; |
1168 | stream->pdata = data; | 1172 | stream->pdata = data; |
@@ -1171,6 +1175,7 @@ struct sst_hsw_stream *sst_hsw_stream_new(struct sst_hsw *hsw, int id, | |||
1171 | 1175 | ||
1172 | /* work to process notification messages */ | 1176 | /* work to process notification messages */ |
1173 | INIT_WORK(&stream->notify_work, hsw_notification_work); | 1177 | INIT_WORK(&stream->notify_work, hsw_notification_work); |
1178 | spin_unlock_irqrestore(&sst->spinlock, flags); | ||
1174 | 1179 | ||
1175 | return stream; | 1180 | return stream; |
1176 | } | 1181 | } |
@@ -1179,6 +1184,8 @@ int sst_hsw_stream_free(struct sst_hsw *hsw, struct sst_hsw_stream *stream) | |||
1179 | { | 1184 | { |
1180 | u32 header; | 1185 | u32 header; |
1181 | int ret = 0; | 1186 | int ret = 0; |
1187 | struct sst_dsp *sst = hsw->dsp; | ||
1188 | unsigned long flags; | ||
1182 | 1189 | ||
1183 | /* dont free DSP streams that are not commited */ | 1190 | /* dont free DSP streams that are not commited */ |
1184 | if (!stream->commited) | 1191 | if (!stream->commited) |
@@ -1200,8 +1207,11 @@ int sst_hsw_stream_free(struct sst_hsw *hsw, struct sst_hsw_stream *stream) | |||
1200 | trace_hsw_stream_free_req(stream, &stream->free_req); | 1207 | trace_hsw_stream_free_req(stream, &stream->free_req); |
1201 | 1208 | ||
1202 | out: | 1209 | out: |
1210 | cancel_work_sync(&stream->notify_work); | ||
1211 | spin_lock_irqsave(&sst->spinlock, flags); | ||
1203 | list_del(&stream->node); | 1212 | list_del(&stream->node); |
1204 | kfree(stream); | 1213 | kfree(stream); |
1214 | spin_unlock_irqrestore(&sst->spinlock, flags); | ||
1205 | 1215 | ||
1206 | return ret; | 1216 | return ret; |
1207 | } | 1217 | } |
@@ -1537,10 +1547,28 @@ int sst_hsw_stream_reset(struct sst_hsw *hsw, struct sst_hsw_stream *stream) | |||
1537 | } | 1547 | } |
1538 | 1548 | ||
1539 | /* Stream pointer positions */ | 1549 | /* Stream pointer positions */ |
1540 | int sst_hsw_get_dsp_position(struct sst_hsw *hsw, | 1550 | u32 sst_hsw_get_dsp_position(struct sst_hsw *hsw, |
1541 | struct sst_hsw_stream *stream) | 1551 | struct sst_hsw_stream *stream) |
1542 | { | 1552 | { |
1543 | return stream->rpos.position; | 1553 | u32 rpos; |
1554 | |||
1555 | sst_dsp_read(hsw->dsp, &rpos, | ||
1556 | stream->reply.read_position_register_address, sizeof(rpos)); | ||
1557 | |||
1558 | return rpos; | ||
1559 | } | ||
1560 | |||
1561 | /* Stream presentation (monotonic) positions */ | ||
1562 | u64 sst_hsw_get_dsp_presentation_position(struct sst_hsw *hsw, | ||
1563 | struct sst_hsw_stream *stream) | ||
1564 | { | ||
1565 | u64 ppos; | ||
1566 | |||
1567 | sst_dsp_read(hsw->dsp, &ppos, | ||
1568 | stream->reply.presentation_position_register_address, | ||
1569 | sizeof(ppos)); | ||
1570 | |||
1571 | return ppos; | ||
1544 | } | 1572 | } |
1545 | 1573 | ||
1546 | int sst_hsw_stream_set_write_position(struct sst_hsw *hsw, | 1574 | int sst_hsw_stream_set_write_position(struct sst_hsw *hsw, |
@@ -1609,7 +1637,7 @@ int sst_hsw_dx_set_state(struct sst_hsw *hsw, | |||
1609 | trace_ipc_request("PM enter Dx state", state); | 1637 | trace_ipc_request("PM enter Dx state", state); |
1610 | 1638 | ||
1611 | ret = ipc_tx_message_wait(hsw, header, &state_, sizeof(state_), | 1639 | ret = ipc_tx_message_wait(hsw, header, &state_, sizeof(state_), |
1612 | dx, sizeof(dx)); | 1640 | dx, sizeof(*dx)); |
1613 | if (ret < 0) { | 1641 | if (ret < 0) { |
1614 | dev_err(hsw->dev, "ipc: error set dx state %d failed\n", state); | 1642 | dev_err(hsw->dev, "ipc: error set dx state %d failed\n", state); |
1615 | return ret; | 1643 | return ret; |