diff -urN linux-mercury-orig/drivers/char/audio_7212.c linux-mercury/drivers/char/audio_7212.c --- linux-mercury-orig/drivers/char/audio_7212.c Sat May 27 11:15:15 2000 +++ linux-mercury/drivers/char/audio_7212.c Tue Feb 20 17:43:55 2001 @@ -18,6 +18,14 @@ * 07-May-2000 - Added hard mute control (sets hardware mute bit) */ + +/* + * JCM 2/20/1 Define to use DAC for volume control rather than + * the volume control chip. This causes volume control to affect + * all outputs rather than just headphone and power amp. + */ +#define LINE_VOLUME + #include #include #include @@ -310,6 +318,59 @@ #endif +#ifdef LINE_VOLUME +/* + * Doing volume and balance with the DAC the DAC + * is a little more tangled. Calculate left and right + * attenuators in DACs using both balance and volume + * information. + */ +static void +pcm1716_volume_balance(unsigned char vol_left, + unsigned char vol_right, int balance) +{ + // Dac attenuation in 0.5dB increments + int left_atten, right_atten; + + // printk("vol_balance: l:%d, r:%d, bal:%d.\n", + // vol_left, vol_right, balance); + + // Left volume + if (vol_left > 30) + left_atten = 100-vol_left; // 0.5 dB per click + else if (vol_left > 0) + left_atten = 160-vol_left*3; // 1.5 dB per click down low + else + left_atten = 255; + + // Right volume + if (vol_right > 30) + right_atten = 100-vol_right; // 0.5 dB per click + else if (vol_right > 0) + right_atten = 160-vol_right*3; // 1.5dB per click down low + else + right_atten = 255; + + // Balance calculation + if (balance > 0) + left_atten += (balance) * 6; // 3dB per balance increment? + if (balance < 0) + right_atten += (-balance) * 6; + + if (left_atten > 255) + left_atten = 255; + if (right_atten > 255) + right_atten = 255; + + // printk("Left: %d, Right: %d\n", left_atten, right_atten); + + pcm1716_control(0, 0x100 | ((255-left_atten) & 0xff)); + pcm1716_control(1, 0x100 | ((255-right_atten) & 0xff)); +} +#endif + + +#ifndef LINE_VOLUME static unsigned char map_oss_to_lm1972(unsigned char oss_value) { /* An OSS value is 0 to 100 - we need to map this to a value @@ -351,7 +412,9 @@ else return 255; } +#endif +#if 0 static unsigned char map_oss_to_pcm1716(int oss_value) { // The hardware supports 255 levels, we only do 100, this doesn't divide @@ -361,7 +424,9 @@ else return 5 + oss_value * 2 + oss_value/2; } +#endif +#ifndef LINE_VOLUME static void map_balance_to_pcm1716(int balance, unsigned char *left, unsigned char *right) { if (balance < 0) { @@ -380,7 +445,9 @@ *right = *left = 255; } } +#endif +#if 0 static int map_lm1972_to_db(int lm_value) { if (lm_value <= 96) { @@ -391,6 +458,7 @@ else return -1000; } +#endif #if 0 static void dump_volume_table(void) @@ -651,6 +719,27 @@ put_user_ret(MIXER_STEREODEVS, (int *)arg, -EFAULT); return 0; +#ifdef LINE_VOLUME + case MIXER_WRITE(SOUND_MIXER_VOLUME): { + int vol; + unsigned char vol_left; + unsigned char vol_right; + + get_user_ret(vol, (int *)arg, -EFAULT); + + /* Equalise from the OSS styleee */ + vol_left = vol & 0xff; + vol_right = (vol >> 8) & 0xff; + + if (vol_left > 100 || vol_right > 100) + return -EINVAL; + + pcm1716_volume_balance(vol_left, vol_right, dev->balance); + + dev->volume = vol; + return 0; + } +#else case MIXER_WRITE(SOUND_MIXER_VOLUME): { int vol; unsigned char vol_left; @@ -672,6 +761,7 @@ dev->volume = vol; return 0; } +#endif case MIXER_READ(SOUND_MIXER_VOLUME): { put_user_ret((int)dev->volume, (int *)arg, -EFAULT); @@ -707,10 +797,32 @@ case EMPEG_MIXER_READ_LOUDNESS: case EMPEG_MIXER_WRITE_LOUDNESS: case EMPEG_MIXER_READ_LOUDNESS_DB: + +#ifdef LINE_VOLUME + case EMPEG_MIXER_WRITE_BALANCE: { + int balance; + unsigned char vol_left; + unsigned char vol_right; + + get_user_ret(balance, (int *)arg, -EFAULT); + + /* balance is 0-15 */ + if (balance < BALANCE_MIN || balance > BALANCE_MAX) + return -EINVAL; + + /* Equalise from the OSS styleee */ + vol_left = dev->volume & 0xff; + vol_right = (dev->volume >> 8) & 0xff; + + pcm1716_volume_balance(vol_left, vol_right, balance); + dev->balance = balance; + return 0; + } +#else case EMPEG_MIXER_WRITE_BALANCE: { int balance; - unsigned char left; - unsigned char right; + unsigned char left; + unsigned char right; get_user_ret(balance, (int *)arg, -EFAULT); @@ -725,6 +837,8 @@ dev->balance = balance; return 0; } +#endif + case EMPEG_MIXER_READ_BALANCE: { put_user_ret(dev->balance, (int *)arg, -EFAULT); return 0; @@ -966,9 +1080,20 @@ clicks from the DAC */ IO_PBDR|=(1<<7); +#ifdef LINE_VOLUME + /* DAC attenuation at maximum */ + pcm1716_control(0,0x100); + pcm1716_control(1,0x100); + + /* 0dB attenuation on volume control chip. This the last + time is gets touched */ + lm1972_control(0,0); + lm1972_control(1,0); +#else /* Control DAC */ pcm1716_control(0,0x1ff); /* No left attenuation */ pcm1716_control(1,0x1ff); /* No right attenuation */ +#endif pcm1716_control(2,0x019); /* DAC muted */ pcm1716_control(3,0x000); /* Standard serial data mode */ #endif