4848#endif
4949
5050#include <audio_utils/resampler.h>
51+ #include <audio_utils/channels.h>
5152
5253#include <tinyhal/audio_config.h>
5354
5758#include <vendor/cirrus/scchal/scc_audio.h>
5859#endif
5960
61+ #ifdef PLATFORM_RCAR3
62+ /* R-Car3 driver supports only 8-channel streams and 48000 sample rate */
63+ /* These values are defined in _frames_ (not bytes) to match the ALSA API */
64+ #define OUT_PERIOD_SIZE_DEFAULT 256
65+ #define OUT_PERIOD_COUNT_DEFAULT 4
66+ #define OUT_CHANNEL_MASK_DEFAULT AUDIO_CHANNEL_OUT_7POINT1
67+ #define OUT_CHANNEL_COUNT_DEFAULT 8
68+ #define OUT_RATE_DEFAULT 48000
69+
70+ #define IN_PERIOD_SIZE_DEFAULT 256
71+ #define IN_PERIOD_COUNT_DEFAULT 4
72+ #define IN_CHANNEL_MASK_DEFAULT AUDIO_CHANNEL_IN_STEREO
73+ #define IN_CHANNEL_COUNT_DEFAULT 8
74+ #define IN_RATE_DEFAULT 48000
75+
76+ #else
77+
6078/* These values are defined in _frames_ (not bytes) to match the ALSA API */
6179#define OUT_PERIOD_SIZE_DEFAULT 256
6280#define OUT_PERIOD_COUNT_DEFAULT 4
7088#define IN_CHANNEL_COUNT_DEFAULT 1
7189#define IN_RATE_DEFAULT 44100
7290
91+ #endif
92+
7393#define IN_PCM_BUFFER_SIZE_DEFAULT \
7494 (IN_PERIOD_SIZE_DEFAULT * IN_CHANNEL_COUNT_DEFAULT * sizeof(uint16_t))
7595
@@ -234,6 +254,9 @@ struct stream_in_pcm {
234254 uint32_t period_size ; /* ... of PCM input */
235255
236256 struct in_resampler resampler ;
257+
258+ void * pre_read_buf ; /* Buffer to store read data before channel adjustment*/
259+ size_t pre_read_buf_size ;
237260};
238261
239262static uint32_t out_get_sample_rate (const struct audio_stream * stream );
@@ -1660,6 +1683,11 @@ static unsigned int in_pcm_cfg_rate(struct stream_in_pcm *in)
16601683
16611684static unsigned int in_pcm_cfg_channel_count (struct stream_in_pcm * in )
16621685{
1686+ #ifdef PLATFORM_RCAR3
1687+ /* On R-Car3 driver supports only 8 channels reading */
1688+ return IN_CHANNEL_COUNT_DEFAULT ;
1689+ #endif
1690+
16631691 if (in -> common .channel_count != 0 ) {
16641692 return in -> common .channel_count ;
16651693 } else {
@@ -1741,6 +1769,22 @@ static int do_open_pcm_input(struct stream_in_pcm *in)
17411769
17421770 ALOGV ("input buffer size=0x%zx" , in -> common .buffer_size );
17431771
1772+ if (in -> common .channel_count != in -> hw_channel_count ) {
1773+ ALOGV ("Setup buffer to read %d channel stream with adjustment (HW only supports %d channel reading)" ,
1774+ in -> common .channel_count , in -> hw_channel_count );
1775+ in -> pre_read_buf_size = in -> common .buffer_size * in -> hw_channel_count / in -> common .channel_count ;
1776+ ALOGV ("in->pre_read_buf_size=0x%zx" , in -> pre_read_buf_size );
1777+ in -> pre_read_buf = calloc (1 , in -> pre_read_buf_size );
1778+ if (!in -> pre_read_buf ) {
1779+ ret = - ENOMEM ;
1780+ goto fail ;
1781+ }
1782+ }
1783+ else {
1784+ in -> pre_read_buf = NULL ;
1785+ in -> pre_read_buf_size = 0 ;
1786+ }
1787+
17441788 /*
17451789 * If the stream rate differs from the PCM rate, we need to
17461790 * create a resampler.
@@ -1758,6 +1802,8 @@ static int do_open_pcm_input(struct stream_in_pcm *in)
17581802fail :
17591803 pcm_close (in -> pcm );
17601804 in -> pcm = NULL ;
1805+ if (in -> pre_read_buf )
1806+ free (in -> pre_read_buf );
17611807exit :
17621808 ALOGV ("-do_open_pcm_input error:%d" , ret );
17631809 return ret ;
@@ -1864,6 +1910,8 @@ static ssize_t do_in_pcm_read(struct audio_stream_in *stream, void *buffer,
18641910 int ret = 0 ;
18651911 struct stream_in_pcm * in = (struct stream_in_pcm * )stream ;
18661912 size_t frames_rq = bytes / in -> common .frame_size ;
1913+ void * read_buf ;
1914+ size_t read_buf_size ;
18671915
18681916 ALOGV ("+do_in_pcm_read %zu" , bytes );
18691917
@@ -1874,10 +1922,39 @@ static ssize_t do_in_pcm_read(struct audio_stream_in *stream, void *buffer,
18741922 goto exit ;
18751923 }
18761924
1925+ if (in -> pre_read_buf ) {
1926+ read_buf = in -> pre_read_buf ;
1927+ read_buf_size = in -> pre_read_buf_size ;
1928+ } else {
1929+ read_buf = buffer ;
1930+ read_buf_size = bytes ;
1931+ }
1932+
18771933 if (in -> resampler .resampler != NULL ) {
1878- ret = read_resampled_frames (in , buffer , frames_rq );
1934+ ret = read_resampled_frames (in , read_buf , frames_rq );
18791935 } else {
1880- ret = pcm_read (in -> pcm , buffer , bytes );
1936+ ret = pcm_read (in -> pcm , read_buf , read_buf_size );
1937+ }
1938+
1939+ if (ret < 0 )
1940+ goto exit ;
1941+
1942+ if (in -> common .channel_count != in -> hw_channel_count ) {
1943+
1944+ ALOGV ("do_in_pcm_read(): Adjust %d channel read stream to %d channel stream" ,
1945+ in -> hw_channel_count , in -> common .channel_count );
1946+
1947+ bytes = adjust_channels (read_buf , /* Input buffer */
1948+ in -> hw_channel_count , /* Input channel count */
1949+ buffer , /* Output buffer */
1950+ in -> common .channel_count , /* Output channel count */
1951+ in -> common .frame_size / in -> common .channel_count , /* Sample size */
1952+ read_buf_size /* Size of input buffer in bytes */
1953+ );
1954+ if (!bytes ) {
1955+ ALOGE ("do_in_pcm_read(): Failed to adjust channels" );
1956+ ret = -1 ;
1957+ }
18811958 }
18821959
18831960 /* Assume any non-negative return is a successful read */
@@ -2015,6 +2092,14 @@ static void do_close_in_pcm(struct audio_stream *stream)
20152092{
20162093 struct stream_in_pcm * in = (struct stream_in_pcm * )stream ;
20172094
2095+ ALOGV ("do_close_in_pcm(%p)" , in );
2096+ if (in && in -> pre_read_buf )
2097+ {
2098+ free (in -> pre_read_buf );
2099+ in -> pre_read_buf = NULL ;
2100+ in -> pre_read_buf_size = 0 ;
2101+ }
2102+
20182103 do_close_in_common (stream );
20192104}
20202105
0 commit comments