summaryrefslogtreecommitdiffstats
path: root/sound/x86
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2017-02-02 18:01:18 -0500
committerTakashi Iwai <tiwai@suse.de>2017-02-06 06:21:10 -0500
commite1b239f371c0c745542cb8108d085ec728e8a69c (patch)
tree5b79452798a340db7c2aabded15f4edf92465c80 /sound/x86
parent1cf05ba2cafa079a943c2cbae51b2f2c2e247466 (diff)
ALSA: x86: Refactor PCM process engine
This is again a big rewrite of the driver; now it touches the code to process PCM stream transfers. The most fundamental change is that the driver may support more than four periods. Instead of keeping the same index between both the ring buffer (with the fixed four buffer descriptors) and the PCM buffer periods, we keep difference indices for both (bd_head and pcm_head fields). In addition, when the periods are more than four, we need to track both head and next indices. That is, we now have three indices: bd_head, pcm_head and pcm_filled. Also, the driver works better for periods < 4, too: the remaining BDs out of four are marked as invalid, so that the hardware skips those BDs in its loop. By this flexibility, we can use even ALSA-lib dmix plugin, which requires 16 periods as default. The buffer size could be up to 20bit, so the max buffer size was increased accordingly. However, the buffer pre-allocation is kept as the old value (600kB) as default. The reason is the limited number of BDs: since it doesn't suffice for the useful SG page management that can fit with the usual page allocator like some other drivers, we have to still allocate continuous pages, hence we shouldn't take too big memories there. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/x86')
-rw-r--r--sound/x86/intel_hdmi_audio.c536
-rw-r--r--sound/x86/intel_hdmi_audio.h24
-rw-r--r--sound/x86/intel_hdmi_lpe_audio.h25
3 files changed, 231 insertions, 354 deletions
diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c
index 57042ef3a480..8978dc9bf579 100644
--- a/sound/x86/intel_hdmi_audio.c
+++ b/sound/x86/intel_hdmi_audio.c
@@ -622,82 +622,6 @@ static void had_prog_dip(struct snd_pcm_substream *substream,
622 had_write_register(intelhaddata, AUD_CNTL_ST, ctrl_state.regval); 622 had_write_register(intelhaddata, AUD_CNTL_ST, ctrl_state.regval);
623} 623}
624 624
625/*
626 * Programs buffer address and length registers
627 * This function programs ring buffer address and length into registers.
628 */
629static int snd_intelhad_prog_buffer(struct snd_pcm_substream *substream,
630 struct snd_intelhad *intelhaddata,
631 int start, int end)
632{
633 u32 ring_buf_addr, ring_buf_size, period_bytes;
634 u8 i, num_periods;
635
636 ring_buf_addr = substream->runtime->dma_addr;
637 ring_buf_size = snd_pcm_lib_buffer_bytes(substream);
638 intelhaddata->stream_info.ring_buf_size = ring_buf_size;
639 period_bytes = frames_to_bytes(substream->runtime,
640 substream->runtime->period_size);
641 num_periods = substream->runtime->periods;
642
643 /*
644 * buffer addr should be 64 byte aligned, period bytes
645 * will be used to calculate addr offset
646 */
647 period_bytes &= ~0x3F;
648
649 /* Hardware supports MAX_PERIODS buffers */
650 if (end >= HAD_MAX_PERIODS)
651 return -EINVAL;
652
653 for (i = start; i <= end; i++) {
654 /* Program the buf registers with addr and len */
655 intelhaddata->buf_info[i].buf_addr = ring_buf_addr +
656 (i * period_bytes);
657 if (i < num_periods-1)
658 intelhaddata->buf_info[i].buf_size = period_bytes;
659 else
660 intelhaddata->buf_info[i].buf_size = ring_buf_size -
661 (i * period_bytes);
662
663 had_write_register(intelhaddata,
664 AUD_BUF_A_ADDR + (i * HAD_REG_WIDTH),
665 intelhaddata->buf_info[i].buf_addr |
666 BIT(0) | BIT(1));
667 had_write_register(intelhaddata,
668 AUD_BUF_A_LENGTH + (i * HAD_REG_WIDTH),
669 period_bytes);
670 intelhaddata->buf_info[i].is_valid = true;
671 }
672 dev_dbg(intelhaddata->dev, "%s:buf[%d-%d] addr=%#x and size=%d\n",
673 __func__, start, end,
674 intelhaddata->buf_info[start].buf_addr,
675 intelhaddata->buf_info[start].buf_size);
676 intelhaddata->valid_buf_cnt = num_periods;
677 return 0;
678}
679
680static int snd_intelhad_read_len(struct snd_intelhad *intelhaddata)
681{
682 int i, retval = 0;
683 u32 len[4];
684
685 for (i = 0; i < 4 ; i++) {
686 had_read_register(intelhaddata,
687 AUD_BUF_A_LENGTH + (i * HAD_REG_WIDTH),
688 &len[i]);
689 if (!len[i])
690 retval++;
691 }
692 if (retval != 1) {
693 for (i = 0; i < 4 ; i++)
694 dev_dbg(intelhaddata->dev, "buf[%d] size=%d\n",
695 i, len[i]);
696 }
697
698 return retval;
699}
700
701static int had_calculate_maud_value(u32 aud_samp_freq, u32 link_rate) 625static int had_calculate_maud_value(u32 aud_samp_freq, u32 link_rate)
702{ 626{
703 u32 maud_val; 627 u32 maud_val;
@@ -885,33 +809,217 @@ static int had_prog_n(u32 aud_samp_freq, u32 *n_param,
885 return 0; 809 return 0;
886} 810}
887 811
812/*
813 * PCM ring buffer handling
814 *
815 * The hardware provides a ring buffer with the fixed 4 buffer descriptors
816 * (BDs). The driver maps these 4 BDs onto the PCM ring buffer. The mapping
817 * moves at each period elapsed. The below illustrates how it works:
818 *
819 * At time=0
820 * PCM | 0 | 1 | 2 | 3 | 4 | 5 | .... |n-1|
821 * BD | 0 | 1 | 2 | 3 |
822 *
823 * At time=1 (period elapsed)
824 * PCM | 0 | 1 | 2 | 3 | 4 | 5 | .... |n-1|
825 * BD | 1 | 2 | 3 | 0 |
826 *
827 * At time=2 (second period elapsed)
828 * PCM | 0 | 1 | 2 | 3 | 4 | 5 | .... |n-1|
829 * BD | 2 | 3 | 0 | 1 |
830 *
831 * The bd_head field points to the index of the BD to be read. It's also the
832 * position to be filled at next. The pcm_head and the pcm_filled fields
833 * point to the indices of the current position and of the next position to
834 * be filled, respectively. For PCM buffer there are both _head and _filled
835 * because they may be difference when nperiods > 4. For example, in the
836 * example above at t=1, bd_head=1 and pcm_head=1 while pcm_filled=5:
837 *
838 * pcm_head (=1) --v v-- pcm_filled (=5)
839 * PCM | 0 | 1 | 2 | 3 | 4 | 5 | .... |n-1|
840 * BD | 1 | 2 | 3 | 0 |
841 * bd_head (=1) --^ ^-- next to fill (= bd_head)
842 *
843 * For nperiods < 4, the remaining BDs out of 4 are marked as invalid, so that
844 * the hardware skips those BDs in the loop.
845 */
846
847#define AUD_BUF_ADDR(x) (AUD_BUF_A_ADDR + (x) * HAD_REG_WIDTH)
848#define AUD_BUF_LEN(x) (AUD_BUF_A_LENGTH + (x) * HAD_REG_WIDTH)
849
850/* Set up a buffer descriptor at the "filled" position */
851static void had_prog_bd(struct snd_pcm_substream *substream,
852 struct snd_intelhad *intelhaddata)
853{
854 int idx = intelhaddata->bd_head;
855 int ofs = intelhaddata->pcmbuf_filled * intelhaddata->period_bytes;
856 u32 addr = substream->runtime->dma_addr + ofs;
857
858 addr |= AUD_BUF_VALID | AUD_BUF_INTR_EN;
859 had_write_register(intelhaddata, AUD_BUF_ADDR(idx), addr);
860 had_write_register(intelhaddata, AUD_BUF_LEN(idx),
861 intelhaddata->period_bytes);
862
863 /* advance the indices to the next */
864 intelhaddata->bd_head++;
865 intelhaddata->bd_head %= intelhaddata->num_bds;
866 intelhaddata->pcmbuf_filled++;
867 intelhaddata->pcmbuf_filled %= substream->runtime->periods;
868}
869
870/* invalidate a buffer descriptor with the given index */
871static void had_invalidate_bd(struct snd_intelhad *intelhaddata,
872 int idx)
873{
874 had_write_register(intelhaddata, AUD_BUF_ADDR(idx), 0);
875 had_write_register(intelhaddata, AUD_BUF_LEN(idx), 0);
876}
877
878/* Initial programming of ring buffer */
879static void had_init_ringbuf(struct snd_pcm_substream *substream,
880 struct snd_intelhad *intelhaddata)
881{
882 struct snd_pcm_runtime *runtime = substream->runtime;
883 int i, num_periods;
884
885 num_periods = runtime->periods;
886 intelhaddata->num_bds = min(num_periods, HAD_NUM_OF_RING_BUFS);
887 intelhaddata->period_bytes =
888 frames_to_bytes(runtime, runtime->period_size);
889 WARN_ON(intelhaddata->period_bytes & 0x3f);
890
891 intelhaddata->bd_head = 0;
892 intelhaddata->pcmbuf_head = 0;
893 intelhaddata->pcmbuf_filled = 0;
894
895 for (i = 0; i < HAD_NUM_OF_RING_BUFS; i++) {
896 if (i < num_periods)
897 had_prog_bd(substream, intelhaddata);
898 else /* invalidate the rest */
899 had_invalidate_bd(intelhaddata, i);
900 }
901
902 intelhaddata->bd_head = 0; /* reset at head again before starting */
903}
904
905/* process a bd, advance to the next */
906static void had_advance_ringbuf(struct snd_pcm_substream *substream,
907 struct snd_intelhad *intelhaddata)
908{
909 int num_periods = substream->runtime->periods;
910
911 /* reprogram the next buffer */
912 had_prog_bd(substream, intelhaddata);
913
914 /* proceed to next */
915 intelhaddata->pcmbuf_head++;
916 intelhaddata->pcmbuf_head %= num_periods;
917}
918
919/* process the current BD(s);
920 * returns the current PCM buffer byte position, or -EPIPE for underrun.
921 */
922static int had_process_ringbuf(struct snd_pcm_substream *substream,
923 struct snd_intelhad *intelhaddata)
924{
925 int len, processed;
926 unsigned long flags;
927
928 processed = 0;
929 spin_lock_irqsave(&intelhaddata->had_spinlock, flags);
930 for (;;) {
931 /* get the remaining bytes on the buffer */
932 had_read_register(intelhaddata,
933 AUD_BUF_LEN(intelhaddata->bd_head),
934 &len);
935 if (len < 0 || len > intelhaddata->period_bytes) {
936 dev_dbg(intelhaddata->dev, "Invalid buf length %d\n",
937 len);
938 len = -EPIPE;
939 goto out;
940 }
941
942 if (len > 0) /* OK, this is the current buffer */
943 break;
944
945 /* len=0 => already empty, check the next buffer */
946 if (++processed >= intelhaddata->num_bds) {
947 len = -EPIPE; /* all empty? - report underrun */
948 goto out;
949 }
950 had_advance_ringbuf(substream, intelhaddata);
951 }
952
953 len = intelhaddata->period_bytes - len;
954 len += intelhaddata->period_bytes * intelhaddata->pcmbuf_head;
955 out:
956 spin_unlock_irqrestore(&intelhaddata->had_spinlock, flags);
957 return len;
958}
959
960/* called from irq handler */
961static void had_process_buffer_done(struct snd_intelhad *intelhaddata)
962{
963 struct snd_pcm_substream *substream;
964
965 if (!intelhaddata->connected)
966 return; /* disconnected? - bail out */
967
968 substream = had_substream_get(intelhaddata);
969 if (!substream)
970 return; /* no stream? - bail out */
971
972 /* process or stop the stream */
973 if (had_process_ringbuf(substream, intelhaddata) < 0)
974 snd_pcm_stop_xrun(substream);
975 else
976 snd_pcm_period_elapsed(substream);
977
978 had_substream_put(intelhaddata);
979}
980
888#define MAX_CNT 0xFF 981#define MAX_CNT 0xFF
889 982
890static void snd_intelhad_handle_underrun(struct snd_intelhad *intelhaddata) 983/*
984 * The interrupt status 'sticky' bits might not be cleared by
985 * setting '1' to that bit once...
986 */
987static void wait_clear_underrun_bit(struct snd_intelhad *intelhaddata)
988{
989 int i;
990 u32 val;
991
992 for (i = 0; i < MAX_CNT; i++) {
993 /* clear bit30, 31 AUD_HDMI_STATUS */
994 had_read_register(intelhaddata, AUD_HDMI_STATUS, &val);
995 if (!(val & AUD_CONFIG_MASK_UNDERRUN))
996 return;
997 had_write_register(intelhaddata, AUD_HDMI_STATUS, val);
998 }
999 dev_err(intelhaddata->dev, "Unable to clear UNDERRUN bits\n");
1000}
1001
1002/* called from irq handler */
1003static void had_process_buffer_underrun(struct snd_intelhad *intelhaddata)
891{ 1004{
892 u32 hdmi_status = 0, i = 0; 1005 struct snd_pcm_substream *substream;
893 1006
894 /* Handle Underrun interrupt within Audio Unit */ 1007 /* Handle Underrun interrupt within Audio Unit */
895 had_write_register(intelhaddata, AUD_CONFIG, 0); 1008 had_write_register(intelhaddata, AUD_CONFIG, 0);
896 /* Reset buffer pointers */ 1009 /* Reset buffer pointers */
897 had_reset_audio(intelhaddata); 1010 had_reset_audio(intelhaddata);
898 /* 1011
899 * The interrupt status 'sticky' bits might not be cleared by 1012 wait_clear_underrun_bit(intelhaddata);
900 * setting '1' to that bit once... 1013
901 */ 1014 if (!intelhaddata->connected)
902 do { /* clear bit30, 31 AUD_HDMI_STATUS */ 1015 return; /* disconnected? - bail out */
903 had_read_register(intelhaddata, AUD_HDMI_STATUS, 1016
904 &hdmi_status); 1017 /* Report UNDERRUN error to above layers */
905 dev_dbg(intelhaddata->dev, "HDMI status =0x%x\n", hdmi_status); 1018 substream = had_substream_get(intelhaddata);
906 if (hdmi_status & AUD_CONFIG_MASK_UNDERRUN) { 1019 if (substream) {
907 i++; 1020 snd_pcm_stop_xrun(substream);
908 had_write_register(intelhaddata, 1021 had_substream_put(intelhaddata);
909 AUD_HDMI_STATUS, hdmi_status); 1022 }
910 } else
911 break;
912 } while (i < MAX_CNT);
913 if (i >= MAX_CNT)
914 dev_err(intelhaddata->dev, "Unable to clear UNDERRUN bits\n");
915} 1023}
916 1024
917/* 1025/*
@@ -957,11 +1065,6 @@ static int had_pcm_open(struct snd_pcm_substream *substream)
957 intelhaddata->stream_info.substream_refcount++; 1065 intelhaddata->stream_info.substream_refcount++;
958 spin_unlock_irq(&intelhaddata->had_spinlock); 1066 spin_unlock_irq(&intelhaddata->had_spinlock);
959 1067
960 /* these are cleared in prepare callback, but just to be sure */
961 intelhaddata->curr_buf = 0;
962 intelhaddata->underrun_count = 0;
963 intelhaddata->stream_info.buffer_rendered = 0;
964
965 return retval; 1068 return retval;
966 error: 1069 error:
967 pm_runtime_put(intelhaddata->dev); 1070 pm_runtime_put(intelhaddata->dev);
@@ -1123,10 +1226,6 @@ static int had_pcm_prepare(struct snd_pcm_substream *substream)
1123 dev_dbg(intelhaddata->dev, "rate=%d\n", runtime->rate); 1226 dev_dbg(intelhaddata->dev, "rate=%d\n", runtime->rate);
1124 dev_dbg(intelhaddata->dev, "channels=%d\n", runtime->channels); 1227 dev_dbg(intelhaddata->dev, "channels=%d\n", runtime->channels);
1125 1228
1126 intelhaddata->curr_buf = 0;
1127 intelhaddata->underrun_count = 0;
1128 intelhaddata->stream_info.buffer_rendered = 0;
1129
1130 /* Get N value in KHz */ 1229 /* Get N value in KHz */
1131 disp_samp_freq = intelhaddata->tmds_clock_speed; 1230 disp_samp_freq = intelhaddata->tmds_clock_speed;
1132 1231
@@ -1148,8 +1247,7 @@ static int had_pcm_prepare(struct snd_pcm_substream *substream)
1148 retval = had_init_audio_ctrl(substream, intelhaddata); 1247 retval = had_init_audio_ctrl(substream, intelhaddata);
1149 1248
1150 /* Prog buffer address */ 1249 /* Prog buffer address */
1151 retval = snd_intelhad_prog_buffer(substream, intelhaddata, 1250 had_init_ringbuf(substream, intelhaddata);
1152 HAD_BUF_TYPE_A, HAD_BUF_TYPE_D);
1153 1251
1154 /* 1252 /*
1155 * Program channel mapping in following order: 1253 * Program channel mapping in following order:
@@ -1168,48 +1266,17 @@ prep_end:
1168static snd_pcm_uframes_t had_pcm_pointer(struct snd_pcm_substream *substream) 1266static snd_pcm_uframes_t had_pcm_pointer(struct snd_pcm_substream *substream)
1169{ 1267{
1170 struct snd_intelhad *intelhaddata; 1268 struct snd_intelhad *intelhaddata;
1171 u32 bytes_rendered = 0; 1269 int len;
1172 u32 t;
1173 int buf_id;
1174 1270
1175 intelhaddata = snd_pcm_substream_chip(substream); 1271 intelhaddata = snd_pcm_substream_chip(substream);
1176 1272
1177 if (!intelhaddata->connected) 1273 if (!intelhaddata->connected)
1178 return SNDRV_PCM_POS_XRUN; 1274 return SNDRV_PCM_POS_XRUN;
1179 1275
1180 /* Use a hw register to calculate sub-period position reports. 1276 len = had_process_ringbuf(substream, intelhaddata);
1181 * This makes PulseAudio happier. 1277 if (len < 0)
1182 */ 1278 return SNDRV_PCM_POS_XRUN;
1183 1279 return bytes_to_frames(substream->runtime, len);
1184 buf_id = intelhaddata->curr_buf % 4;
1185 had_read_register(intelhaddata,
1186 AUD_BUF_A_LENGTH + (buf_id * HAD_REG_WIDTH), &t);
1187
1188 if ((t == 0) || (t == ((u32)-1L))) {
1189 intelhaddata->underrun_count++;
1190 dev_dbg(intelhaddata->dev,
1191 "discovered buffer done for buf %d, count = %d\n",
1192 buf_id, intelhaddata->underrun_count);
1193
1194 if (intelhaddata->underrun_count > (HAD_MIN_PERIODS/2)) {
1195 dev_dbg(intelhaddata->dev,
1196 "assume audio_codec_reset, underrun = %d - do xrun\n",
1197 intelhaddata->underrun_count);
1198 return SNDRV_PCM_POS_XRUN;
1199 }
1200 } else {
1201 /* Reset Counter */
1202 intelhaddata->underrun_count = 0;
1203 }
1204
1205 t = intelhaddata->buf_info[buf_id].buf_size - t;
1206
1207 if (intelhaddata->stream_info.buffer_rendered)
1208 div_u64_rem(intelhaddata->stream_info.buffer_rendered,
1209 intelhaddata->stream_info.ring_buf_size,
1210 &(bytes_rendered));
1211
1212 return bytes_to_frames(substream->runtime, bytes_rendered + t);
1213} 1280}
1214 1281
1215/* 1282/*
@@ -1278,179 +1345,9 @@ out:
1278 return retval; 1345 return retval;
1279} 1346}
1280 1347
1281static inline int had_chk_intrmiss(struct snd_intelhad *intelhaddata,
1282 enum intel_had_aud_buf_type buf_id)
1283{
1284 int i, intr_count = 0;
1285 enum intel_had_aud_buf_type buff_done;
1286 u32 buf_size, buf_addr;
1287
1288 buff_done = buf_id;
1289
1290 intr_count = snd_intelhad_read_len(intelhaddata);
1291 if (intr_count > 1) {
1292 /* In case of active playback */
1293 dev_err(intelhaddata->dev,
1294 "Driver detected %d missed buffer done interrupt(s)\n",
1295 (intr_count - 1));
1296 if (intr_count > 3)
1297 return intr_count;
1298
1299 buf_id += (intr_count - 1);
1300 /* Reprogram registers*/
1301 for (i = buff_done; i < buf_id; i++) {
1302 int j = i % 4;
1303
1304 buf_size = intelhaddata->buf_info[j].buf_size;
1305 buf_addr = intelhaddata->buf_info[j].buf_addr;
1306 had_write_register(intelhaddata,
1307 AUD_BUF_A_LENGTH +
1308 (j * HAD_REG_WIDTH), buf_size);
1309 had_write_register(intelhaddata,
1310 AUD_BUF_A_ADDR+(j * HAD_REG_WIDTH),
1311 (buf_addr | BIT(0) | BIT(1)));
1312 }
1313 buf_id = buf_id % 4;
1314 intelhaddata->buff_done = buf_id;
1315 }
1316
1317 return intr_count;
1318}
1319
1320/* called from irq handler */
1321static int had_process_buffer_done(struct snd_intelhad *intelhaddata)
1322{
1323 u32 len = 1;
1324 enum intel_had_aud_buf_type buf_id;
1325 enum intel_had_aud_buf_type buff_done;
1326 struct pcm_stream_info *stream;
1327 struct snd_pcm_substream *substream;
1328 u32 buf_size;
1329 int intr_count;
1330 unsigned long flags;
1331
1332 stream = &intelhaddata->stream_info;
1333 intr_count = 1;
1334
1335 spin_lock_irqsave(&intelhaddata->had_spinlock, flags);
1336 if (!intelhaddata->connected) {
1337 spin_unlock_irqrestore(&intelhaddata->had_spinlock, flags);
1338 dev_dbg(intelhaddata->dev,
1339 "%s:Device already disconnected\n", __func__);
1340 return 0;
1341 }
1342 buf_id = intelhaddata->curr_buf;
1343 intelhaddata->buff_done = buf_id;
1344 buff_done = intelhaddata->buff_done;
1345 buf_size = intelhaddata->buf_info[buf_id].buf_size;
1346
1347 /* Every debug statement has an implication
1348 * of ~5msec. Thus, avoid having >3 debug statements
1349 * for each buffer_done handling.
1350 */
1351
1352 /* Check for any intr_miss in case of active playback */
1353 if (stream->running) {
1354 intr_count = had_chk_intrmiss(intelhaddata, buf_id);
1355 if (!intr_count || (intr_count > 3)) {
1356 spin_unlock_irqrestore(&intelhaddata->had_spinlock,
1357 flags);
1358 dev_err(intelhaddata->dev,
1359 "HAD SW state in non-recoverable mode\n");
1360 return 0;
1361 }
1362 buf_id += (intr_count - 1);
1363 buf_id = buf_id % 4;
1364 }
1365
1366 intelhaddata->buf_info[buf_id].is_valid = true;
1367 if (intelhaddata->valid_buf_cnt-1 == buf_id) {
1368 if (stream->running)
1369 intelhaddata->curr_buf = HAD_BUF_TYPE_A;
1370 } else
1371 intelhaddata->curr_buf = buf_id + 1;
1372
1373 spin_unlock_irqrestore(&intelhaddata->had_spinlock, flags);
1374
1375 if (!intelhaddata->connected) {
1376 dev_dbg(intelhaddata->dev, "HDMI cable plugged-out\n");
1377 return 0;
1378 }
1379
1380 /* Reprogram the registers with addr and length */
1381 had_write_register(intelhaddata,
1382 AUD_BUF_A_LENGTH + (buf_id * HAD_REG_WIDTH),
1383 buf_size);
1384 had_write_register(intelhaddata,
1385 AUD_BUF_A_ADDR + (buf_id * HAD_REG_WIDTH),
1386 intelhaddata->buf_info[buf_id].buf_addr |
1387 BIT(0) | BIT(1));
1388
1389 had_read_register(intelhaddata,
1390 AUD_BUF_A_LENGTH + (buf_id * HAD_REG_WIDTH),
1391 &len);
1392 dev_dbg(intelhaddata->dev, "%s:Enabled buf[%d]\n", __func__, buf_id);
1393
1394 /* In case of actual data,
1395 * report buffer_done to above ALSA layer
1396 */
1397 substream = had_substream_get(intelhaddata);
1398 if (substream) {
1399 buf_size = intelhaddata->buf_info[buf_id].buf_size;
1400 intelhaddata->stream_info.buffer_rendered +=
1401 (intr_count * buf_size);
1402 snd_pcm_period_elapsed(substream);
1403 had_substream_put(intelhaddata);
1404 }
1405
1406 return 0;
1407}
1408
1409/* called from irq handler */
1410static int had_process_buffer_underrun(struct snd_intelhad *intelhaddata)
1411{
1412 enum intel_had_aud_buf_type buf_id;
1413 struct pcm_stream_info *stream;
1414 struct snd_pcm_substream *substream;
1415 unsigned long flags;
1416 int connected;
1417
1418 stream = &intelhaddata->stream_info;
1419
1420 spin_lock_irqsave(&intelhaddata->had_spinlock, flags);
1421 buf_id = intelhaddata->curr_buf;
1422 intelhaddata->buff_done = buf_id;
1423 connected = intelhaddata->connected;
1424 if (stream->running)
1425 intelhaddata->curr_buf = HAD_BUF_TYPE_A;
1426
1427 spin_unlock_irqrestore(&intelhaddata->had_spinlock, flags);
1428
1429 dev_dbg(intelhaddata->dev, "Enter:%s buf_id=%d, stream_running=%d\n",
1430 __func__, buf_id, stream->running);
1431
1432 snd_intelhad_handle_underrun(intelhaddata);
1433
1434 if (!connected) {
1435 dev_dbg(intelhaddata->dev,
1436 "%s:Device already disconnected\n", __func__);
1437 return 0;
1438 }
1439
1440 /* Report UNDERRUN error to above layers */
1441 substream = had_substream_get(intelhaddata);
1442 if (substream) {
1443 snd_pcm_stop_xrun(substream);
1444 had_substream_put(intelhaddata);
1445 }
1446
1447 return 0;
1448}
1449
1450/* process hot plug, called from wq with mutex locked */ 1348/* process hot plug, called from wq with mutex locked */
1451static void had_process_hot_plug(struct snd_intelhad *intelhaddata) 1349static void had_process_hot_plug(struct snd_intelhad *intelhaddata)
1452{ 1350{
1453 enum intel_had_aud_buf_type buf_id;
1454 struct snd_pcm_substream *substream; 1351 struct snd_pcm_substream *substream;
1455 1352
1456 spin_lock_irq(&intelhaddata->had_spinlock); 1353 spin_lock_irq(&intelhaddata->had_spinlock);
@@ -1460,17 +1357,12 @@ static void had_process_hot_plug(struct snd_intelhad *intelhaddata)
1460 return; 1357 return;
1461 } 1358 }
1462 1359
1463 buf_id = intelhaddata->curr_buf;
1464 intelhaddata->buff_done = buf_id;
1465 intelhaddata->connected = true; 1360 intelhaddata->connected = true;
1466 dev_dbg(intelhaddata->dev, 1361 dev_dbg(intelhaddata->dev,
1467 "%s @ %d:DEBUG PLUG/UNPLUG : HAD_DRV_CONNECTED\n", 1362 "%s @ %d:DEBUG PLUG/UNPLUG : HAD_DRV_CONNECTED\n",
1468 __func__, __LINE__); 1363 __func__, __LINE__);
1469 spin_unlock_irq(&intelhaddata->had_spinlock); 1364 spin_unlock_irq(&intelhaddata->had_spinlock);
1470 1365
1471 dev_dbg(intelhaddata->dev, "Processing HOT_PLUG, buf_id = %d\n",
1472 buf_id);
1473
1474 /* Safety check */ 1366 /* Safety check */
1475 substream = had_substream_get(intelhaddata); 1367 substream = had_substream_get(intelhaddata);
1476 if (substream) { 1368 if (substream) {
@@ -1487,11 +1379,8 @@ static void had_process_hot_plug(struct snd_intelhad *intelhaddata)
1487/* process hot unplug, called from wq with mutex locked */ 1379/* process hot unplug, called from wq with mutex locked */
1488static void had_process_hot_unplug(struct snd_intelhad *intelhaddata) 1380static void had_process_hot_unplug(struct snd_intelhad *intelhaddata)
1489{ 1381{
1490 enum intel_had_aud_buf_type buf_id;
1491 struct snd_pcm_substream *substream; 1382 struct snd_pcm_substream *substream;
1492 1383
1493 buf_id = intelhaddata->curr_buf;
1494
1495 substream = had_substream_get(intelhaddata); 1384 substream = had_substream_get(intelhaddata);
1496 1385
1497 spin_lock_irq(&intelhaddata->had_spinlock); 1386 spin_lock_irq(&intelhaddata->had_spinlock);
@@ -1862,13 +1751,12 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
1862 dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); 1751 dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
1863 dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); 1752 dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
1864 1753
1865 /* allocate dma pages for ALSA stream operations 1754 /* allocate dma pages;
1866 * memory allocated is based on size, not max value 1755 * try to allocate 600k buffer as default which is large enough
1867 * thus using same argument for max & size
1868 */ 1756 */
1869 snd_pcm_lib_preallocate_pages_for_all(pcm, 1757 snd_pcm_lib_preallocate_pages_for_all(pcm,
1870 SNDRV_DMA_TYPE_DEV, NULL, 1758 SNDRV_DMA_TYPE_DEV, NULL,
1871 HAD_MAX_BUFFER, HAD_MAX_BUFFER); 1759 HAD_DEFAULT_BUFFER, HAD_MAX_BUFFER);
1872 1760
1873 /* create controls */ 1761 /* create controls */
1874 for (i = 0; i < ARRAY_SIZE(had_controls); i++) { 1762 for (i = 0; i < ARRAY_SIZE(had_controls); i++) {
diff --git a/sound/x86/intel_hdmi_audio.h b/sound/x86/intel_hdmi_audio.h
index 9f713a8a88bc..7e2546b853ca 100644
--- a/sound/x86/intel_hdmi_audio.h
+++ b/sound/x86/intel_hdmi_audio.h
@@ -64,24 +64,15 @@
64 64
65struct pcm_stream_info { 65struct pcm_stream_info {
66 struct snd_pcm_substream *substream; 66 struct snd_pcm_substream *substream;
67 u64 buffer_rendered;
68 u32 ring_buf_size;
69 int substream_refcount; 67 int substream_refcount;
70 bool running; 68 bool running;
71}; 69};
72 70
73struct ring_buf_info {
74 u32 buf_addr;
75 u32 buf_size;
76 u8 is_valid;
77};
78
79/* 71/*
80 * struct snd_intelhad - intelhad driver structure 72 * struct snd_intelhad - intelhad driver structure
81 * 73 *
82 * @card: ptr to hold card details 74 * @card: ptr to hold card details
83 * @connected: the monitor connection status 75 * @connected: the monitor connection status
84 * @buf_info: ring buffer info
85 * @stream_info: stream information 76 * @stream_info: stream information
86 * @eld: holds ELD info 77 * @eld: holds ELD info
87 * @curr_buf: pointer to hold current active ring buf 78 * @curr_buf: pointer to hold current active ring buf
@@ -91,26 +82,29 @@ struct ring_buf_info {
91 * @buff_done: id of current buffer done intr 82 * @buff_done: id of current buffer done intr
92 * @dev: platoform device handle 83 * @dev: platoform device handle
93 * @chmap: holds channel map info 84 * @chmap: holds channel map info
94 * @underrun_count: PCM stream underrun counter
95 */ 85 */
96struct snd_intelhad { 86struct snd_intelhad {
97 struct snd_card *card; 87 struct snd_card *card;
98 bool connected; 88 bool connected;
99 struct ring_buf_info buf_info[HAD_NUM_OF_RING_BUFS];
100 struct pcm_stream_info stream_info; 89 struct pcm_stream_info stream_info;
101 unsigned char eld[HDMI_MAX_ELD_BYTES]; 90 unsigned char eld[HDMI_MAX_ELD_BYTES];
102 bool dp_output; 91 bool dp_output;
103 enum intel_had_aud_buf_type curr_buf;
104 int valid_buf_cnt;
105 unsigned int aes_bits; 92 unsigned int aes_bits;
106 spinlock_t had_spinlock; 93 spinlock_t had_spinlock;
107 enum intel_had_aud_buf_type buff_done;
108 struct device *dev; 94 struct device *dev;
109 struct snd_pcm_chmap *chmap; 95 struct snd_pcm_chmap *chmap;
110 int underrun_count;
111 int tmds_clock_speed; 96 int tmds_clock_speed;
112 int link_rate; 97 int link_rate;
113 98
99 /* ring buffer (BD) position index */
100 unsigned int bd_head;
101 /* PCM buffer position indices */
102 unsigned int pcmbuf_head; /* being processed */
103 unsigned int pcmbuf_filled; /* to be filled */
104
105 unsigned int num_bds; /* number of BDs */
106 unsigned int period_bytes; /* PCM period size in bytes */
107
114 /* internal stuff */ 108 /* internal stuff */
115 int irq; 109 int irq;
116 void __iomem *mmio_start; 110 void __iomem *mmio_start;
diff --git a/sound/x86/intel_hdmi_lpe_audio.h b/sound/x86/intel_hdmi_lpe_audio.h
index be9783910a3a..ca4212dca94e 100644
--- a/sound/x86/intel_hdmi_lpe_audio.h
+++ b/sound/x86/intel_hdmi_lpe_audio.h
@@ -28,13 +28,13 @@
28#define HAD_MAX_CHANNEL 8 28#define HAD_MAX_CHANNEL 8
29#define HAD_NUM_OF_RING_BUFS 4 29#define HAD_NUM_OF_RING_BUFS 4
30 30
31/* Assume 192KHz, 8channel, 25msec period */ 31/* max 20bit address, aligned to 64 */
32#define HAD_MAX_BUFFER (600*1024) 32#define HAD_MAX_BUFFER ((1024 * 1024 - 1) & ~0x3f)
33#define HAD_MIN_BUFFER (32*1024) 33#define HAD_DEFAULT_BUFFER (600 * 1024) /* default prealloc size */
34#define HAD_MAX_PERIODS 4 34#define HAD_MAX_PERIODS 256 /* arbitrary, but should suffice */
35#define HAD_MIN_PERIODS 4 35#define HAD_MIN_PERIODS 2
36#define HAD_MAX_PERIOD_BYTES (HAD_MAX_BUFFER/HAD_MIN_PERIODS) 36#define HAD_MAX_PERIOD_BYTES ((HAD_MAX_BUFFER / HAD_MIN_PERIODS) & ~0x3f)
37#define HAD_MIN_PERIOD_BYTES 256 37#define HAD_MIN_PERIOD_BYTES 1024 /* might be smaller */
38#define HAD_FIFO_SIZE 0 /* fifo not being used */ 38#define HAD_FIFO_SIZE 0 /* fifo not being used */
39#define MAX_SPEAKERS 8 39#define MAX_SPEAKERS 8
40 40
@@ -82,14 +82,6 @@
82/* Naud Value */ 82/* Naud Value */
83#define DP_NAUD_VAL 32768 83#define DP_NAUD_VAL 32768
84 84
85/* enum intel_had_aud_buf_type - HDMI controller ring buffer types */
86enum intel_had_aud_buf_type {
87 HAD_BUF_TYPE_A = 0,
88 HAD_BUF_TYPE_B = 1,
89 HAD_BUF_TYPE_C = 2,
90 HAD_BUF_TYPE_D = 3,
91};
92
93/* HDMI Controller register offsets - audio domain common */ 85/* HDMI Controller register offsets - audio domain common */
94/* Base address for below regs = 0x65000 */ 86/* Base address for below regs = 0x65000 */
95enum hdmi_ctrl_reg_offset_common { 87enum hdmi_ctrl_reg_offset_common {
@@ -274,6 +266,9 @@ union aud_buf_addr {
274 u32 regval; 266 u32 regval;
275}; 267};
276 268
269#define AUD_BUF_VALID (1U << 0)
270#define AUD_BUF_INTR_EN (1U << 1)
271
277/* Length of Audio Buffer */ 272/* Length of Audio Buffer */
278union aud_buf_len { 273union aud_buf_len {
279 struct { 274 struct {