From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Benjamin Herrenschmidt To: linuxppc-dev list , linuxppc64-dev Content-Type: text/plain Date: Sun, 08 Jan 2006 15:52:36 +1100 Message-Id: <1136695956.30123.44.camel@localhost.localdomain> Mime-Version: 1.0 Subject: [PATCH] powerpc: Fix PowerMac sound i2c List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , My patch reworking the PowerMac i2c code break the sound drivers as they used to rely on some broken behaviour of i2c-keywest that is gone now. This patch should fix them (tested on a g5 with alsa only). It might also fix an oops if the alsa driver hits an unsupported chip. Signed-off-by: Benjamin Herrenschmidt Index: linux-work/sound/ppc/tumbler.c =================================================================== --- linux-work.orig/sound/ppc/tumbler.c 2005-11-24 17:19:14.000000000 +1100 +++ linux-work/sound/ppc/tumbler.c 2006-01-08 15:18:09.000000000 +1100 @@ -137,6 +137,22 @@ static int send_init_client(pmac_keywest return 0; } +static int tumbler_write_block(struct i2c_client *client, u8 reg, int len, + u8 *values) +{ + union i2c_smbus_data data; + int err; + + data.block[0] = len; + memcpy(&data.block[1], values, len); + err = i2c_smbus_xfer(client->adapter, client->addr, client->flags, + I2C_SMBUS_WRITE, reg, I2C_SMBUS_I2C_BLOCK_DATA, + &data); + return err; +} + + + static int tumbler_init_client(pmac_keywest_t *i2c) { @@ -239,8 +255,7 @@ static int tumbler_set_master_volume(pma block[4] = (right_vol >> 8) & 0xff; block[5] = (right_vol >> 0) & 0xff; - if (i2c_smbus_write_block_data(mix->i2c.client, TAS_REG_VOL, - 6, block) < 0) { + if (tumbler_write_block(mix->i2c.client, TAS_REG_VOL, 6, block) < 0) { snd_printk("failed to set volume \n"); return -EINVAL; } @@ -340,8 +355,7 @@ static int tumbler_set_drc(pmac_tumbler_ val[1] = 0; } - if (i2c_smbus_write_block_data(mix->i2c.client, TAS_REG_DRC, - 2, val) < 0) { + if (tumbler_write_block(mix->i2c.client, TAS_REG_DRC, 2, val) < 0) { snd_printk("failed to set DRC\n"); return -EINVAL; } @@ -376,8 +390,7 @@ static int snapper_set_drc(pmac_tumbler_ val[4] = 0x60; val[5] = 0xa0; - if (i2c_smbus_write_block_data(mix->i2c.client, TAS_REG_DRC, - 6, val) < 0) { + if (tumbler_write_block(mix->i2c.client, TAS_REG_DRC, 6, val) < 0) { snd_printk("failed to set DRC\n"); return -EINVAL; } @@ -481,8 +494,8 @@ static int tumbler_set_mono_volume(pmac_ vol = info->table[vol]; for (i = 0; i < info->bytes; i++) block[i] = (vol >> ((info->bytes - i - 1) * 8)) & 0xff; - if (i2c_smbus_write_block_data(mix->i2c.client, info->reg, - info->bytes, block) < 0) { + if (tumbler_write_block(mix->i2c.client, info->reg, + info->bytes, block) < 0) { snd_printk("failed to set mono volume %d\n", info->index); return -EINVAL; } @@ -611,7 +624,7 @@ static int snapper_set_mix_vol1(pmac_tum for (j = 0; j < 3; j++) block[i * 3 + j] = (vol >> ((2 - j) * 8)) & 0xff; } - if (i2c_smbus_write_block_data(mix->i2c.client, reg, 9, block) < 0) { + if (tumbler_write_block(mix->i2c.client, reg, 9, block) < 0) { snd_printk("failed to set mono volume %d\n", reg); return -EINVAL; } Index: linux-work/sound/oss/dmasound/tas_common.h =================================================================== --- linux-work.orig/sound/oss/dmasound/tas_common.h 2005-11-24 17:19:14.000000000 +1100 +++ linux-work/sound/oss/dmasound/tas_common.h 2006-01-08 15:33:29.000000000 +1100 @@ -157,6 +157,21 @@ tas_mono_to_stereo(uint mono) return mono | (mono<<8); } +static int tas_write_block(struct i2c_client *client, u8 reg, int len, u8 *vals) +{ + union i2c_smbus_data data; + int err; + + data.block[0] = len; + memcpy(&data.block[1], vals, len); + err = i2c_smbus_xfer(client->adapter, client->addr, client->flags, + I2C_SMBUS_WRITE, reg, I2C_SMBUS_I2C_BLOCK_DATA, + &data); + return err; +} + + + /* * Todo: make these functions a bit more efficient ! */ @@ -178,10 +193,8 @@ tas_write_register( struct tas_data_t *s if (write_mode & WRITE_SHADOW) memcpy(self->shadow[reg_num],data,reg_width); if (write_mode & WRITE_HW) { - rc=i2c_smbus_write_block_data(self->client, - reg_num, - reg_width, - data); + rc = tas_write_block(self->client, reg_num, + reg_width, data); if (rc < 0) { printk("tas: I2C block write failed \n"); return rc; @@ -199,10 +212,8 @@ tas_sync_register( struct tas_data_t *se if (reg_width==0 || self==NULL) return -EINVAL; - rc=i2c_smbus_write_block_data(self->client, - reg_num, - reg_width, - self->shadow[reg_num]); + rc = tas_write_block(self->client, reg_num, + reg_width, self->shadow[reg_num]); if (rc < 0) { printk("tas: I2C block write failed \n"); return rc; Index: linux-work/sound/ppc/pmac.c =================================================================== --- linux-work.orig/sound/ppc/pmac.c 2005-12-19 16:13:48.000000000 +1100 +++ linux-work/sound/ppc/pmac.c 2006-01-08 15:37:10.000000000 +1100 @@ -74,7 +74,7 @@ static int snd_pmac_dbdma_alloc(pmac_t * static void snd_pmac_dbdma_free(pmac_t *chip, pmac_dbdma_t *rec) { - if (rec) { + if (rec->space) { unsigned int rsize = sizeof(struct dbdma_cmd) * (rec->size + 1); dma_free_coherent(&chip->pdev->dev, rsize, rec->space, rec->dma_base); @@ -895,6 +895,7 @@ static int __init snd_pmac_detect(pmac_t chip->can_capture = 1; chip->num_freqs = ARRAY_SIZE(awacs_freqs); chip->freq_table = awacs_freqs; + chip->pdev = NULL; chip->control_mask = MASK_IEPC | MASK_IEE | 0x11; /* default */