[alsa-devel] [PATCH 1/8] ASoC: Make all codecs depend on rather than selecting I2C
The I2C layer uses I/O operations that aren't available on all architectures and since select bypasses Kconfig dependency checking selecting I2C breaks builds like allmodconfig on some architectures.
Signed-off-by: Mark Brown broonie@opensource.wolfsonmicro.com --- sound/soc/codecs/Kconfig | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 5d77dc3..13ae4fd 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -1,6 +1,6 @@ config SND_SOC_ALL_CODECS tristate "Build all ASoC CODEC drivers" - select I2C + depends on I2C select SPI select SND_SOC_AK4535 select SND_SOC_UDA1380
From: Jean Delvare khali@linux-fr.org
Convert the uda1380 codec driver to the new (standard) device driver binding model.
Signed-off-by: Jean Delvare khali@linux-fr.org Signed-off-by: Mark Brown broonie@opensource.wolfsonmicro.com --- sound/soc/codecs/uda1380.c | 109 +++++++++++++++++++++---------------------- sound/soc/codecs/uda1380.h | 1 + 2 files changed, 54 insertions(+), 56 deletions(-)
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 807318f..f0c8043 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -701,87 +701,86 @@ static struct snd_soc_device *uda1380_socdev;
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-#define I2C_DRIVERID_UDA1380 0xfefe /* liam - need a proper id */ - -static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END }; - -/* Magic definition of all other variables and things */ -I2C_CLIENT_INSMOD; - -static struct i2c_driver uda1380_i2c_driver; -static struct i2c_client client_template; - -/* If the i2c layer weren't so broken, we could pass this kind of data - around */ - -static int uda1380_codec_probe(struct i2c_adapter *adap, int addr, int kind) +static int uda1380_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) { struct snd_soc_device *socdev = uda1380_socdev; struct uda1380_setup_data *setup = socdev->codec_data; struct snd_soc_codec *codec = socdev->codec; - struct i2c_client *i2c; int ret;
- if (addr != setup->i2c_address) - return -ENODEV; - - client_template.adapter = adap; - client_template.addr = addr; - - i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); - if (i2c == NULL) - return -ENOMEM; - i2c_set_clientdata(i2c, codec); codec->control_data = i2c;
- ret = i2c_attach_client(i2c); - if (ret < 0) { - pr_err("uda1380: failed to attach codec at addr %x\n", addr); - goto err; - } - ret = uda1380_init(socdev, setup->dac_clk); - if (ret < 0) { + if (ret < 0) pr_err("uda1380: failed to initialise UDA1380\n"); - goto err; - } - return ret;
-err: - kfree(i2c); return ret; }
-static int uda1380_i2c_detach(struct i2c_client *client) +static int uda1380_i2c_remove(struct i2c_client *client) { struct snd_soc_codec *codec = i2c_get_clientdata(client); - i2c_detach_client(client); kfree(codec->reg_cache); - kfree(client); return 0; }
-static int uda1380_i2c_attach(struct i2c_adapter *adap) -{ - return i2c_probe(adap, &addr_data, uda1380_codec_probe); -} +static const struct i2c_device_id uda1380_i2c_id[] = { + { "uda1380", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id);
static struct i2c_driver uda1380_i2c_driver = { .driver = { .name = "UDA1380 I2C Codec", .owner = THIS_MODULE, }, - .id = I2C_DRIVERID_UDA1380, - .attach_adapter = uda1380_i2c_attach, - .detach_client = uda1380_i2c_detach, - .command = NULL, + .probe = uda1380_i2c_probe, + .remove = uda1380_i2c_remove, + .id_table = uda1380_i2c_id, };
-static struct i2c_client client_template = { - .name = "UDA1380", - .driver = &uda1380_i2c_driver, -}; +static int uda1380_add_i2c_device(struct platform_device *pdev, + const struct uda1380_setup_data *setup) +{ + struct i2c_board_info info; + struct i2c_adapter *adapter; + struct i2c_client *client; + int ret; + + ret = i2c_add_driver(&uda1380_i2c_driver); + if (ret != 0) { + dev_err(&pdev->dev, "can't add i2c driver\n"); + return ret; + } + + memset(&info, 0, sizeof(struct i2c_board_info)); + info.addr = setup->i2c_address; + strlcpy(info.type, "uda1380", I2C_NAME_SIZE); + + adapter = i2c_get_adapter(setup->i2c_bus); + if (!adapter) { + dev_err(&pdev->dev, "can't get i2c adapter %d\n", + setup->i2c_bus); + goto err_driver; + } + + client = i2c_new_device(adapter, &info); + i2c_put_adapter(adapter); + if (!client) { + dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", + (unsigned int)info.addr); + goto err_driver; + } + + return 0; + +err_driver: + i2c_del_driver(&uda1380_i2c_driver); + return -ENODEV; +} #endif
static int uda1380_probe(struct platform_device *pdev) @@ -806,11 +805,8 @@ static int uda1380_probe(struct platform_device *pdev) uda1380_socdev = socdev; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) if (setup->i2c_address) { - normal_i2c[0] = setup->i2c_address; codec->hw_write = (hw_write_t)i2c_master_send; - ret = i2c_add_driver(&uda1380_i2c_driver); - if (ret != 0) - printk(KERN_ERR "can't add i2c driver"); + ret = uda1380_add_i2c_device(pdev, setup); } #else /* Add other interfaces here */ @@ -833,6 +829,7 @@ static int uda1380_remove(struct platform_device *pdev) snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + i2c_unregister_device(codec->control_data); i2c_del_driver(&uda1380_i2c_driver); #endif kfree(codec); diff --git a/sound/soc/codecs/uda1380.h b/sound/soc/codecs/uda1380.h index 50c603e..c55c17a 100644 --- a/sound/soc/codecs/uda1380.h +++ b/sound/soc/codecs/uda1380.h @@ -73,6 +73,7 @@ #define R23_AGC_EN 0x0001
struct uda1380_setup_data { + int i2c_bus; unsigned short i2c_address; int dac_clk; #define UDA1380_DAC_CLK_SYSCLK 0
From: Jean Delvare khali@linux-fr.org
Convert the ak4535 codec driver to the new (standard) device driver binding model. After this change, AK4535 devices are no longer discovered automatically and must instead be instantiated explicitly.
Signed-off-by: Jean Delvare khali@linux-fr.org Signed-off-by: Mark Brown broonie@opensource.wolfsonmicro.com --- sound/soc/codecs/ak4535.c | 110 +++++++++++++++++++++----------------------- sound/soc/codecs/ak4535.h | 1 + 2 files changed, 54 insertions(+), 57 deletions(-)
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index 7da9f46..e512cd7 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c @@ -535,87 +535,85 @@ static struct snd_soc_device *ak4535_socdev;
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-#define I2C_DRIVERID_AK4535 0xfefe /* liam - need a proper id */ - -static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END }; - -/* Magic definition of all other variables and things */ -I2C_CLIENT_INSMOD; - -static struct i2c_driver ak4535_i2c_driver; -static struct i2c_client client_template; - -/* If the i2c layer weren't so broken, we could pass this kind of data - around */ -static int ak4535_codec_probe(struct i2c_adapter *adap, int addr, int kind) +static int ak4535_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) { struct snd_soc_device *socdev = ak4535_socdev; - struct ak4535_setup_data *setup = socdev->codec_data; struct snd_soc_codec *codec = socdev->codec; - struct i2c_client *i2c; int ret;
- if (addr != setup->i2c_address) - return -ENODEV; - - client_template.adapter = adap; - client_template.addr = addr; - - i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); - if (i2c == NULL) - return -ENOMEM; - i2c_set_clientdata(i2c, codec); codec->control_data = i2c;
- ret = i2c_attach_client(i2c); - if (ret < 0) { - printk(KERN_ERR "failed to attach codec at addr %x\n", addr); - goto err; - } - ret = ak4535_init(socdev); - if (ret < 0) { + if (ret < 0) printk(KERN_ERR "failed to initialise AK4535\n"); - goto err; - } - return ret;
-err: - kfree(i2c); return ret; }
-static int ak4535_i2c_detach(struct i2c_client *client) +static int ak4535_i2c_remove(struct i2c_client *client) { struct snd_soc_codec *codec = i2c_get_clientdata(client); - i2c_detach_client(client); kfree(codec->reg_cache); - kfree(client); return 0; }
-static int ak4535_i2c_attach(struct i2c_adapter *adap) -{ - return i2c_probe(adap, &addr_data, ak4535_codec_probe); -} +static const struct i2c_device_id ak4535_i2c_id[] = { + { "ak4535", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ak4535_i2c_id);
-/* corgi i2c codec control layer */ static struct i2c_driver ak4535_i2c_driver = { .driver = { .name = "AK4535 I2C Codec", .owner = THIS_MODULE, }, - .id = I2C_DRIVERID_AK4535, - .attach_adapter = ak4535_i2c_attach, - .detach_client = ak4535_i2c_detach, - .command = NULL, + .probe = ak4535_i2c_probe, + .remove = ak4535_i2c_remove, + .id_table = ak4535_i2c_id, };
-static struct i2c_client client_template = { - .name = "AK4535", - .driver = &ak4535_i2c_driver, -}; +static int ak4535_add_i2c_device(struct platform_device *pdev, + const struct ak4535_setup_data *setup) +{ + struct i2c_board_info info; + struct i2c_adapter *adapter; + struct i2c_client *client; + int ret; + + ret = i2c_add_driver(&ak4535_i2c_driver); + if (ret != 0) { + dev_err(&pdev->dev, "can't add i2c driver\n"); + return ret; + } + + memset(&info, 0, sizeof(struct i2c_board_info)); + info.addr = setup->i2c_address; + strlcpy(info.type, "ak4535", I2C_NAME_SIZE); + + adapter = i2c_get_adapter(setup->i2c_bus); + if (!adapter) { + dev_err(&pdev->dev, "can't get i2c adapter %d\n", + setup->i2c_bus); + goto err_driver; + } + + client = i2c_new_device(adapter, &info); + i2c_put_adapter(adapter); + if (!client) { + dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", + (unsigned int)info.addr); + goto err_driver; + } + + return 0; + +err_driver: + i2c_del_driver(&ak4535_i2c_driver); + return -ENODEV; +} #endif
static int ak4535_probe(struct platform_device *pdev) @@ -648,12 +646,9 @@ static int ak4535_probe(struct platform_device *pdev) ak4535_socdev = socdev; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) if (setup->i2c_address) { - normal_i2c[0] = setup->i2c_address; codec->hw_write = (hw_write_t)i2c_master_send; codec->hw_read = (hw_read_t)i2c_master_recv; - ret = i2c_add_driver(&ak4535_i2c_driver); - if (ret != 0) - printk(KERN_ERR "can't add i2c driver"); + ret = ak4535_add_i2c_device(pdev, setup); } #else /* Add other interfaces here */ @@ -678,6 +673,7 @@ static int ak4535_remove(struct platform_device *pdev) snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + i2c_unregister_device(codec->control_data); i2c_del_driver(&ak4535_i2c_driver); #endif kfree(codec->private_data); diff --git a/sound/soc/codecs/ak4535.h b/sound/soc/codecs/ak4535.h index e9fe30e..c7a5870 100644 --- a/sound/soc/codecs/ak4535.h +++ b/sound/soc/codecs/ak4535.h @@ -37,6 +37,7 @@ #define AK4535_CACHEREGNUM 0x10
struct ak4535_setup_data { + int i2c_bus; unsigned short i2c_address; };
From: Jean Delvare khali@linux-fr.org
Convert the wm8750 codec driver to the new (standard) device driver binding model.
Signed-off-by: Jean Delvare khali@linux-fr.org Signed-off-by: Mark Brown broonie@opensource.wolfsonmicro.com --- sound/soc/codecs/wm8750.c | 105 +++++++++++++++++++++++---------------------- sound/soc/codecs/wm8750.h | 1 + sound/soc/pxa/spitz.c | 1 + 3 files changed, 55 insertions(+), 52 deletions(-)
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index dd1f554..34d8465 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -846,83 +846,86 @@ static struct snd_soc_device *wm8750_socdev; * low = 0x1a * high = 0x1b */ -static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
-/* Magic definition of all other variables and things */ -I2C_CLIENT_INSMOD; - -static struct i2c_driver wm8750_i2c_driver; -static struct i2c_client client_template; - -static int wm8750_codec_probe(struct i2c_adapter *adap, int addr, int kind) +static int wm8750_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) { struct snd_soc_device *socdev = wm8750_socdev; - struct wm8750_setup_data *setup = socdev->codec_data; struct snd_soc_codec *codec = socdev->codec; - struct i2c_client *i2c; int ret;
- if (addr != setup->i2c_address) - return -ENODEV; - - client_template.adapter = adap; - client_template.addr = addr; - - i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); - if (i2c == NULL) - return -ENOMEM; - i2c_set_clientdata(i2c, codec); codec->control_data = i2c;
- ret = i2c_attach_client(i2c); - if (ret < 0) { - pr_err("failed to attach codec at addr %x\n", addr); - goto err; - } - ret = wm8750_init(socdev); - if (ret < 0) { + if (ret < 0) pr_err("failed to initialise WM8750\n"); - goto err; - } - return ret;
-err: - kfree(i2c); return ret; }
-static int wm8750_i2c_detach(struct i2c_client *client) +static int wm8750_i2c_remove(struct i2c_client *client) { struct snd_soc_codec *codec = i2c_get_clientdata(client); - i2c_detach_client(client); kfree(codec->reg_cache); - kfree(client); return 0; }
-static int wm8750_i2c_attach(struct i2c_adapter *adap) -{ - return i2c_probe(adap, &addr_data, wm8750_codec_probe); -} +static const struct i2c_device_id wm8750_i2c_id[] = { + { "wm8750", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id);
-/* corgi i2c codec control layer */ static struct i2c_driver wm8750_i2c_driver = { .driver = { .name = "WM8750 I2C Codec", .owner = THIS_MODULE, }, - .id = I2C_DRIVERID_WM8750, - .attach_adapter = wm8750_i2c_attach, - .detach_client = wm8750_i2c_detach, - .command = NULL, + .probe = wm8750_i2c_probe, + .remove = wm8750_i2c_remove, + .id_table = wm8750_i2c_id, };
-static struct i2c_client client_template = { - .name = "WM8750", - .driver = &wm8750_i2c_driver, -}; +static int wm8750_add_i2c_device(struct platform_device *pdev, + const struct wm8750_setup_data *setup) +{ + struct i2c_board_info info; + struct i2c_adapter *adapter; + struct i2c_client *client; + int ret; + + ret = i2c_add_driver(&wm8750_i2c_driver); + if (ret != 0) { + dev_err(&pdev->dev, "can't add i2c driver\n"); + return ret; + } + + memset(&info, 0, sizeof(struct i2c_board_info)); + info.addr = setup->i2c_address; + strlcpy(info.type, "wm8750", I2C_NAME_SIZE); + + adapter = i2c_get_adapter(setup->i2c_bus); + if (!adapter) { + dev_err(&pdev->dev, "can't get i2c adapter %d\n", + setup->i2c_bus); + goto err_driver; + } + + client = i2c_new_device(adapter, &info); + i2c_put_adapter(adapter); + if (!client) { + dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", + (unsigned int)info.addr); + goto err_driver; + } + + return 0; + +err_driver: + i2c_del_driver(&wm8750_i2c_driver); + return -ENODEV; +} #endif
static int wm8750_probe(struct platform_device *pdev) @@ -954,11 +957,8 @@ static int wm8750_probe(struct platform_device *pdev)
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) if (setup->i2c_address) { - normal_i2c[0] = setup->i2c_address; codec->hw_write = (hw_write_t)i2c_master_send; - ret = i2c_add_driver(&wm8750_i2c_driver); - if (ret != 0) - printk(KERN_ERR "can't add i2c driver"); + ret = wm8750_add_i2c_device(pdev, setup); } #else /* Add other interfaces here */ @@ -1002,6 +1002,7 @@ static int wm8750_remove(struct platform_device *pdev) snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + i2c_unregister_device(codec->control_data); i2c_del_driver(&wm8750_i2c_driver); #endif kfree(codec->private_data); diff --git a/sound/soc/codecs/wm8750.h b/sound/soc/codecs/wm8750.h index 8ef30e6..fe6c80f 100644 --- a/sound/soc/codecs/wm8750.h +++ b/sound/soc/codecs/wm8750.h @@ -58,6 +58,7 @@ #define WM8750_SYSCLK 0
struct wm8750_setup_data { + int i2c_bus; unsigned short i2c_address; };
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index 37cb768..3d4738c 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -337,6 +337,7 @@ static struct snd_soc_machine snd_soc_machine_spitz = {
/* spitz audio private data */ static struct wm8750_setup_data spitz_wm8750_setup = { + .i2c_bus = 0, .i2c_address = 0x1b, };
From: Jean Delvare khali@linux-fr.org
Convert the wm8731 codec driver to the new (standard) device driver binding model.
Signed-off-by: Jean Delvare khali@linux-fr.org Tested-by: Manuel Lauss mano@roarinelk.homelinux.net Signed-off-by: Mark Brown broonie@opensource.wolfsonmicro.com --- sound/soc/at91/eti_b1_wm8731.c | 1 + sound/soc/codecs/wm8731.c | 108 +++++++++++++++++++-------------------- sound/soc/codecs/wm8731.h | 1 + sound/soc/pxa/corgi.c | 1 + sound/soc/pxa/poodle.c | 1 + 5 files changed, 57 insertions(+), 55 deletions(-)
diff --git a/sound/soc/at91/eti_b1_wm8731.c b/sound/soc/at91/eti_b1_wm8731.c index b81d6b2..684781e 100644 --- a/sound/soc/at91/eti_b1_wm8731.c +++ b/sound/soc/at91/eti_b1_wm8731.c @@ -243,6 +243,7 @@ static struct snd_soc_machine snd_soc_machine_eti_b1 = { };
static struct wm8731_setup_data eti_b1_wm8731_setup = { + .i2c_bus = 0, .i2c_address = 0x1a, };
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 9402fca..5814f9b 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -570,86 +570,86 @@ static struct snd_soc_device *wm8731_socdev; * low = 0x1a * high = 0x1b */ -static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
-/* Magic definition of all other variables and things */ -I2C_CLIENT_INSMOD; - -static struct i2c_driver wm8731_i2c_driver; -static struct i2c_client client_template; - -/* If the i2c layer weren't so broken, we could pass this kind of data - around */ - -static int wm8731_codec_probe(struct i2c_adapter *adap, int addr, int kind) +static int wm8731_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) { struct snd_soc_device *socdev = wm8731_socdev; - struct wm8731_setup_data *setup = socdev->codec_data; struct snd_soc_codec *codec = socdev->codec; - struct i2c_client *i2c; int ret;
- if (addr != setup->i2c_address) - return -ENODEV; - - client_template.adapter = adap; - client_template.addr = addr; - - i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); - if (i2c == NULL) - return -ENOMEM; - i2c_set_clientdata(i2c, codec); codec->control_data = i2c;
- ret = i2c_attach_client(i2c); - if (ret < 0) { - pr_err("failed to attach codec at addr %x\n", addr); - goto err; - } - ret = wm8731_init(socdev); - if (ret < 0) { + if (ret < 0) pr_err("failed to initialise WM8731\n"); - goto err; - } - return ret;
-err: - kfree(i2c); return ret; }
-static int wm8731_i2c_detach(struct i2c_client *client) +static int wm8731_i2c_remove(struct i2c_client *client) { struct snd_soc_codec *codec = i2c_get_clientdata(client); - i2c_detach_client(client); kfree(codec->reg_cache); - kfree(client); return 0; }
-static int wm8731_i2c_attach(struct i2c_adapter *adap) -{ - return i2c_probe(adap, &addr_data, wm8731_codec_probe); -} +static const struct i2c_device_id wm8731_i2c_id[] = { + { "wm8731", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id);
-/* corgi i2c codec control layer */ static struct i2c_driver wm8731_i2c_driver = { .driver = { .name = "WM8731 I2C Codec", .owner = THIS_MODULE, }, - .id = I2C_DRIVERID_WM8731, - .attach_adapter = wm8731_i2c_attach, - .detach_client = wm8731_i2c_detach, - .command = NULL, + .probe = wm8731_i2c_probe, + .remove = wm8731_i2c_remove, + .id_table = wm8731_i2c_id, };
-static struct i2c_client client_template = { - .name = "WM8731", - .driver = &wm8731_i2c_driver, -}; +static int wm8731_add_i2c_device(struct platform_device *pdev, + const struct wm8731_setup_data *setup) +{ + struct i2c_board_info info; + struct i2c_adapter *adapter; + struct i2c_client *client; + int ret; + + ret = i2c_add_driver(&wm8731_i2c_driver); + if (ret != 0) { + dev_err(&pdev->dev, "can't add i2c driver\n"); + return ret; + } + + memset(&info, 0, sizeof(struct i2c_board_info)); + info.addr = setup->i2c_address; + strlcpy(info.type, "wm8731", I2C_NAME_SIZE); + + adapter = i2c_get_adapter(setup->i2c_bus); + if (!adapter) { + dev_err(&pdev->dev, "can't get i2c adapter %d\n", + setup->i2c_bus); + goto err_driver; + } + + client = i2c_new_device(adapter, &info); + i2c_put_adapter(adapter); + if (!client) { + dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", + (unsigned int)info.addr); + goto err_driver; + } + + return 0; + +err_driver: + i2c_del_driver(&wm8731_i2c_driver); + return -ENODEV; +} #endif
static int wm8731_probe(struct platform_device *pdev) @@ -682,11 +682,8 @@ static int wm8731_probe(struct platform_device *pdev) wm8731_socdev = socdev; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) if (setup->i2c_address) { - normal_i2c[0] = setup->i2c_address; codec->hw_write = (hw_write_t)i2c_master_send; - ret = i2c_add_driver(&wm8731_i2c_driver); - if (ret != 0) - printk(KERN_ERR "can't add i2c driver"); + ret = wm8731_add_i2c_device(pdev, setup); } #else /* Add other interfaces here */ @@ -711,6 +708,7 @@ static int wm8731_remove(struct platform_device *pdev) snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + i2c_unregister_device(codec->control_data); i2c_del_driver(&wm8731_i2c_driver); #endif kfree(codec->private_data); diff --git a/sound/soc/codecs/wm8731.h b/sound/soc/codecs/wm8731.h index 99f2e3c..0f81239 100644 --- a/sound/soc/codecs/wm8731.h +++ b/sound/soc/codecs/wm8731.h @@ -35,6 +35,7 @@ #define WM8731_DAI 0
struct wm8731_setup_data { + int i2c_bus; unsigned short i2c_address; };
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index 0a53f72..72b7a51 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -330,6 +330,7 @@ static struct snd_soc_machine snd_soc_machine_corgi = {
/* corgi audio private data */ static struct wm8731_setup_data corgi_wm8731_setup = { + .i2c_bus = 0, .i2c_address = 0x1b, };
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index a4697f7..f84f7d8 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -284,6 +284,7 @@ static struct snd_soc_machine snd_soc_machine_poodle = {
/* poodle audio private data */ static struct wm8731_setup_data poodle_wm8731_setup = { + .i2c_bus = 0, .i2c_address = 0x1b, };
From: Jean Delvare khali@linux-fr.org
Convert the wm8990 codec driver to the new (standard) device driver binding model. After this change, WM8990 devices are no longer discovered automatically and must instead be instantiated explicitly.
Signed-off-by: Jean Delvare khali@linux-fr.org Signed-off-by: Mark Brown broonie@opensource.wolfsonmicro.com --- sound/soc/codecs/wm8990.c | 103 +++++++++++++++++++++++---------------------- sound/soc/codecs/wm8990.h | 1 + 2 files changed, 54 insertions(+), 50 deletions(-)
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index dd995ef..e1bb505 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -1477,81 +1477,86 @@ static struct snd_soc_device *wm8990_socdev; * low = 0x34 * high = 0x36 */ -static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
-/* Magic definition of all other variables and things */ -I2C_CLIENT_INSMOD; - -static struct i2c_driver wm8990_i2c_driver; -static struct i2c_client client_template; - -static int wm8990_codec_probe(struct i2c_adapter *adap, int addr, int kind) +static int wm8990_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) { struct snd_soc_device *socdev = wm8990_socdev; - struct wm8990_setup_data *setup = socdev->codec_data; struct snd_soc_codec *codec = socdev->codec; - struct i2c_client *i2c; int ret;
- if (addr != setup->i2c_address) - return -ENODEV; - - client_template.adapter = adap; - client_template.addr = addr; - - i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); - if (i2c == NULL) - return -ENOMEM; - i2c_set_clientdata(i2c, codec); codec->control_data = i2c;
- ret = i2c_attach_client(i2c); - if (ret < 0) { - pr_err("failed to attach codec at addr %x\n", addr); - goto err; - } - ret = wm8990_init(socdev); - if (ret < 0) { + if (ret < 0) pr_err("failed to initialise WM8990\n"); - goto err; - } - return ret;
-err: - kfree(i2c); return ret; }
-static int wm8990_i2c_detach(struct i2c_client *client) +static int wm8990_i2c_remove(struct i2c_client *client) { struct snd_soc_codec *codec = i2c_get_clientdata(client); - i2c_detach_client(client); kfree(codec->reg_cache); - kfree(client); return 0; }
-static int wm8990_i2c_attach(struct i2c_adapter *adap) -{ - return i2c_probe(adap, &addr_data, wm8990_codec_probe); -} +static const struct i2c_device_id wm8990_i2c_id[] = { + { "wm8990", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, wm8990_i2c_id);
static struct i2c_driver wm8990_i2c_driver = { .driver = { .name = "WM8990 I2C Codec", .owner = THIS_MODULE, }, - .attach_adapter = wm8990_i2c_attach, - .detach_client = wm8990_i2c_detach, - .command = NULL, + .probe = wm8990_i2c_probe, + .remove = wm8990_i2c_remove, + .id_table = wm8990_i2c_id, };
-static struct i2c_client client_template = { - .name = "WM8990", - .driver = &wm8990_i2c_driver, -}; +static int wm8990_add_i2c_device(struct platform_device *pdev, + const struct wm8990_setup_data *setup) +{ + struct i2c_board_info info; + struct i2c_adapter *adapter; + struct i2c_client *client; + int ret; + + ret = i2c_add_driver(&wm8990_i2c_driver); + if (ret != 0) { + dev_err(&pdev->dev, "can't add i2c driver\n"); + return ret; + } + + memset(&info, 0, sizeof(struct i2c_board_info)); + info.addr = setup->i2c_address; + strlcpy(info.type, "wm8990", I2C_NAME_SIZE); + + adapter = i2c_get_adapter(setup->i2c_bus); + if (!adapter) { + dev_err(&pdev->dev, "can't get i2c adapter %d\n", + setup->i2c_bus); + goto err_driver; + } + + client = i2c_new_device(adapter, &info); + i2c_put_adapter(adapter); + if (!client) { + dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", + (unsigned int)info.addr); + goto err_driver; + } + + return 0; + +err_driver: + i2c_del_driver(&wm8990_i2c_driver); + return -ENODEV; +} #endif
static int wm8990_probe(struct platform_device *pdev) @@ -1584,11 +1589,8 @@ static int wm8990_probe(struct platform_device *pdev)
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) if (setup->i2c_address) { - normal_i2c[0] = setup->i2c_address; codec->hw_write = (hw_write_t)i2c_master_send; - ret = i2c_add_driver(&wm8990_i2c_driver); - if (ret != 0) - printk(KERN_ERR "can't add i2c driver"); + ret = wm8990_add_i2c_device(pdev, setup); } #else /* Add other interfaces here */ @@ -1612,6 +1614,7 @@ static int wm8990_remove(struct platform_device *pdev) snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + i2c_unregister_device(codec->control_data); i2c_del_driver(&wm8990_i2c_driver); #endif kfree(codec->private_data); diff --git a/sound/soc/codecs/wm8990.h b/sound/soc/codecs/wm8990.h index 0a08325..0e192f3 100644 --- a/sound/soc/codecs/wm8990.h +++ b/sound/soc/codecs/wm8990.h @@ -827,6 +827,7 @@ #define WM8990_AINRMUX_PWR_BIT 3
struct wm8990_setup_data { + unsigned i2c_bus; unsigned short i2c_address; };
From: Cliff Cai cliff.cai@analog.com
[Modified to allow runtime selection between I2C and SPI and to select SPI_MASTER for all codecs build so this is included. -- broonie]
Signed-off-by: Cliff Cai cliff.cai@analog.com Signed-off-by: Bryan Wu cooloney@kernel.org Signed-off-by: Mark Brown broonie@opensource.wolfsonmicro.com --- sound/soc/codecs/Kconfig | 1 + sound/soc/codecs/wm8731.c | 71 +++++++++++++++++++++++++++++++++++++++++++- sound/soc/codecs/wm8731.h | 1 + 3 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 13ae4fd..cceac73 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -2,6 +2,7 @@ config SND_SOC_ALL_CODECS tristate "Build all ASoC CODEC drivers" depends on I2C select SPI + select SPI_MASTER select SND_SOC_AK4535 select SND_SOC_UDA1380 select SND_SOC_WM8510 diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 5814f9b..975befd 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -19,6 +19,7 @@ #include <linux/pm.h> #include <linux/i2c.h> #include <linux/platform_device.h> +#include <linux/spi/spi.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -652,6 +653,61 @@ err_driver: } #endif
+#if defined(CONFIG_SPI_MASTER) +static int __devinit wm8731_spi_probe(struct spi_device *spi) +{ + struct snd_soc_device *socdev = wm8731_socdev; + struct snd_soc_codec *codec = socdev->codec; + int ret; + + codec->control_data = spi; + + ret = wm8731_init(socdev); + if (ret < 0) + dev_err(&spi->dev, "failed to initialise WM8731\n"); + + return ret; +} + +static int __devexit wm8731_spi_remove(struct spi_device *spi) +{ + return 0; +} + +static struct spi_driver wm8731_spi_driver = { + .driver = { + .name = "wm8731", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = wm8731_spi_probe, + .remove = __devexit_p(wm8731_spi_remove), +}; + +static int wm8731_spi_write(struct spi_device *spi, const char *data, int len) +{ + struct spi_transfer t; + struct spi_message m; + u16 msg[2]; + + if (len <= 0) + return 0; + + msg[0] = (data[0] << 8) + data[1]; + + spi_message_init(&m); + memset(&t, 0, (sizeof t)); + + t.tx_buf = &msg[0]; + t.len = len; + + spi_message_add_tail(&t, &m); + spi_sync(spi, &m); + + return len; +} +#endif /* CONFIG_SPI_MASTER */ + static int wm8731_probe(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); @@ -680,13 +736,21 @@ static int wm8731_probe(struct platform_device *pdev) INIT_LIST_HEAD(&codec->dapm_paths);
wm8731_socdev = socdev; + ret = -ENODEV; + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) if (setup->i2c_address) { codec->hw_write = (hw_write_t)i2c_master_send; ret = wm8731_add_i2c_device(pdev, setup); } -#else - /* Add other interfaces here */ +#endif +#if defined(CONFIG_SPI_MASTER) + if (setup->spi) { + codec->hw_write = (hw_write_t)wm8731_spi_write; + ret = spi_register_driver(&wm8731_spi_driver); + if (ret != 0) + printk(KERN_ERR "can't add spi driver"); + } #endif
if (ret != 0) { @@ -711,6 +775,9 @@ static int wm8731_remove(struct platform_device *pdev) i2c_unregister_device(codec->control_data); i2c_del_driver(&wm8731_i2c_driver); #endif +#if defined(CONFIG_SPI_MASTER) + spi_unregister_driver(&wm8731_spi_driver); +#endif kfree(codec->private_data); kfree(codec);
diff --git a/sound/soc/codecs/wm8731.h b/sound/soc/codecs/wm8731.h index 0f81239..95190e9 100644 --- a/sound/soc/codecs/wm8731.h +++ b/sound/soc/codecs/wm8731.h @@ -35,6 +35,7 @@ #define WM8731_DAI 0
struct wm8731_setup_data { + int spi; int i2c_bus; unsigned short i2c_address; };
Currently the boiler plate code used by most ASoC codecs to provide a placeholder for SPI access suggests making the selection of SPI a compile time option which is suboptimal when trying to build kernels supporting multiple systems. Change this template to suggest allowing runtime selection instead.
Leave the drivers not yet converted to new style I2C access for now to avoid collisions.
Signed-off-by: Mark Brown broonie@opensource.wolfsonmicro.com --- sound/soc/codecs/ak4535.c | 6 +++--- sound/soc/codecs/uda1380.c | 6 +++--- sound/soc/codecs/wm8750.c | 6 +++--- sound/soc/codecs/wm8990.c | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index e512cd7..088cf99 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c @@ -622,7 +622,7 @@ static int ak4535_probe(struct platform_device *pdev) struct ak4535_setup_data *setup; struct snd_soc_codec *codec; struct ak4535_priv *ak4535; - int ret = 0; + int ret;
printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION);
@@ -644,14 +644,14 @@ static int ak4535_probe(struct platform_device *pdev) INIT_LIST_HEAD(&codec->dapm_paths);
ak4535_socdev = socdev; + ret = -ENODEV; + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) if (setup->i2c_address) { codec->hw_write = (hw_write_t)i2c_master_send; codec->hw_read = (hw_read_t)i2c_master_recv; ret = ak4535_add_i2c_device(pdev, setup); } -#else - /* Add other interfaces here */ #endif
if (ret != 0) { diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index f0c8043..d206d7f 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -788,7 +788,7 @@ static int uda1380_probe(struct platform_device *pdev) struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct uda1380_setup_data *setup; struct snd_soc_codec *codec; - int ret = 0; + int ret;
pr_info("UDA1380 Audio Codec %s", UDA1380_VERSION);
@@ -803,13 +803,13 @@ static int uda1380_probe(struct platform_device *pdev) INIT_LIST_HEAD(&codec->dapm_paths);
uda1380_socdev = socdev; + ret = -ENODEV; + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) if (setup->i2c_address) { codec->hw_write = (hw_write_t)i2c_master_send; ret = uda1380_add_i2c_device(pdev, setup); } -#else - /* Add other interfaces here */ #endif
if (ret != 0) diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 34d8465..9847aa0 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -934,7 +934,7 @@ static int wm8750_probe(struct platform_device *pdev) struct wm8750_setup_data *setup = socdev->codec_data; struct snd_soc_codec *codec; struct wm8750_priv *wm8750; - int ret = 0; + int ret;
pr_info("WM8750 Audio Codec %s", WM8750_VERSION); codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); @@ -955,13 +955,13 @@ static int wm8750_probe(struct platform_device *pdev) wm8750_socdev = socdev; INIT_DELAYED_WORK(&codec->delayed_work, wm8750_work);
+ ret = -ENODEV; + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) if (setup->i2c_address) { codec->hw_write = (hw_write_t)i2c_master_send; ret = wm8750_add_i2c_device(pdev, setup); } -#else - /* Add other interfaces here */ #endif
if (ret != 0) { diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index e1bb505..63410d7 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -1565,7 +1565,7 @@ static int wm8990_probe(struct platform_device *pdev) struct wm8990_setup_data *setup; struct snd_soc_codec *codec; struct wm8990_priv *wm8990; - int ret = 0; + int ret;
pr_info("WM8990 Audio Codec %s\n", WM8990_VERSION);
@@ -1587,13 +1587,13 @@ static int wm8990_probe(struct platform_device *pdev) INIT_LIST_HEAD(&codec->dapm_paths); wm8990_socdev = socdev;
+ ret = -ENODEV; + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) if (setup->i2c_address) { codec->hw_write = (hw_write_t)i2c_master_send; ret = wm8990_add_i2c_device(pdev, setup); } -#else - /* Add other interfaces here */ #endif
if (ret != 0) {
On Monday 01 September 2008 18:47, Mark Brown wrote:
From: Cliff Cai cliff.cai@analog.com
[Modified to allow runtime selection between I2C and SPI and to select SPI_MASTER for all codecs build so this is included. -- broonie]
Signed-off-by: Cliff Cai cliff.cai@analog.com Signed-off-by: Bryan Wu cooloney@kernel.org Signed-off-by: Mark Brown broonie@opensource.wolfsonmicro.com
What architecture has this SPI code been tested on? Specifically, what endianess?
--- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c
+static int wm8731_spi_write(struct spi_device *spi, const char *data, int len) +{
- struct spi_transfer t;
- struct spi_message m;
- u16 msg[2];
- if (len <= 0)
return 0;
- msg[0] = (data[0] << 8) + data[1];
- spi_message_init(&m);
- memset(&t, 0, (sizeof t));
- t.tx_buf = &msg[0];
- t.len = len;
- spi_message_add_tail(&t, &m);
- spi_sync(spi, &m);
- return len;
+}
Is this _spi_write arch BE/LE proof?
Alan
On Wed, Sep 03, 2008 at 05:01:46PM +0100, Alan Horstmann wrote:
On Monday 01 September 2008 18:47, Mark Brown wrote:
What architecture has this SPI code been tested on? Specifically, what endianess?
Blackfin.
On Thu, Sep 4, 2008 at 12:01 AM, Alan Horstmann gineera@aspect135.co.uk wrote:
On Monday 01 September 2008 18:47, Mark Brown wrote:
From: Cliff Cai cliff.cai@analog.com
[Modified to allow runtime selection between I2C and SPI and to select SPI_MASTER for all codecs build so this is included. -- broonie]
Signed-off-by: Cliff Cai cliff.cai@analog.com Signed-off-by: Bryan Wu cooloney@kernel.org Signed-off-by: Mark Brown broonie@opensource.wolfsonmicro.com
What architecture has this SPI code been tested on? Specifically, what endianess?
We tested on Blackfin machine and it's little-endian.
-Bryan
--- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c
+static int wm8731_spi_write(struct spi_device *spi, const char *data, int len) +{
struct spi_transfer t;
struct spi_message m;
u16 msg[2];
if (len <= 0)
return 0;
msg[0] = (data[0] << 8) + data[1];
spi_message_init(&m);
memset(&t, 0, (sizeof t));
t.tx_buf = &msg[0];
t.len = len;
spi_message_add_tail(&t, &m);
spi_sync(spi, &m);
return len;
+}
Is this _spi_write arch BE/LE proof?
Alan
On Thursday 04 September 2008 02:46, you wrote:
On Thu, Sep 4, 2008 at 12:01 AM, Alan Horstmann gineera@aspect135.co.uk
wrote:
On Monday 01 September 2008 18:47, Mark Brown wrote:
[Modified to allow runtime selection between I2C and SPI and to select SPI_MASTER for all codecs build so this is included. -- broonie]
What architecture has this SPI code been tested on? Specifically, what endianess?
We tested on Blackfin machine and it's little-endian.
-Bryan
Thanks, Mark, Bryan. We are trying this on AT91. What we see is the 2 bytes of the SPI message swapped on the bus (data then address) and I am suspicious of this _spi_write function. As I am in unfamiliar territory, please be patient if I am mistaken. Analysis below...
+static int wm8731_spi_write(struct spi_device *spi, const char *data, int len) +{
struct spi_transfer t;
struct spi_message m;
u16 msg[2];
if (len <= 0)
return 0;
msg[0] = (data[0] << 8) + data[1];
spi_message_init(&m);
memset(&t, 0, (sizeof t));
t.tx_buf = &msg[0];
t.len = len;
spi_message_add_tail(&t, &m);
spi_sync(spi, &m);
return len;
+}
I assume that spi_transfer sends bytes in order, from the tx_buf position, and it seems clear that data[0] is the high byte that should go first. As msg[2] is u16 (why?), I would have thought that the byte at &msg[0] would be the low byte on LE, high byte on BE so it would only be correct on BE.
Changing the code to use u8 msg[2]; and simply, but explicitly msg[0] = data[0]; msg[1] = data[1];
fixes the problem here.
Comments?
Alan
On Thu, Sep 04, 2008 at 11:48:29AM +0100, Alan Horstmann wrote:
I assume that spi_transfer sends bytes in order, from the tx_buf position, and it seems clear that data[0] is the high byte that should go first. As msg[2] is u16 (why?), I would have thought that the byte at &msg[0] would be the low byte on LE, high byte on BE so it would only be correct on BE.
Your analysis makes sense to me.
Changing the code to use
...
fixes the problem here.
Could you supply a patch, please?
On Monday 08 September 2008 14:52, you wrote:
On Thu, Sep 04, 2008 at 11:48:29AM +0100, Alan Horstmann wrote:
I assume that spi_transfer sends bytes in order, from the tx_buf position, and it seems clear that data[0] is the high byte that should go first. As msg[2] is u16 (why?), I would have thought that the byte at &msg[0] would be the low byte on LE, high byte on BE so it would only be correct on BE.
Your analysis makes sense to me.
Changing the code to use
...
fixes the problem here.
Could you supply a patch, please?
Attached and here inline is the small change we applied to ensure the byte order is correct in the _spi_write function. Note we observed the spi bus with a fast Digital Oscilloscope, and could readily see the bytes were originally reversed in our case (AT91SAM9260). Our build is set to LE, but I have no idea why the write should be fine on Blackfin-LE without this change.
With just this one change we have been successful in running the codec over spi. At present we do have an issue with dapm during capture -nothing is being turned on! Any pointers would be appreciated.
Alan
wm8731_spi_write_byte_order.patch
--- wm8731-orig.c 2008-09-08 17:16:52.000000000 +0100 +++ wm8731.c 2008-09-08 21:03:16.000000000 +0100 @@ -688,12 +688,13 @@ { struct spi_transfer t; struct spi_message m; - u16 msg[2]; + u8 msg[2];
if (len <= 0) return 0;
- msg[0] = (data[0] << 8) + data[1]; + msg[0] = data[0]; + msg[1] = data[1];
spi_message_init(&m); memset(&t, 0, (sizeof t));
On Mon, Sep 08, 2008 at 09:27:13PM +0100, Alan Horstmann wrote:
Attached and here inline is the small change we applied to ensure the byte order is correct in the _spi_write function. Note we observed the spi bus
I take it you're happy to give this your Signed-off-by?
With just this one change we have been successful in running the codec over spi. At present we do have an issue with dapm during capture -nothing is being turned on! Any pointers would be appreciated.
If you define DEBUG when building soc-dapm.c (a define at the top of the source file will do the trick) then it will be very verbose about the decisions it's making - that will normally point out the problem. Probably either one of the input controls is not configured to make a path from the input pins to the ADC or the input has been mistakenly marked as disabled.
Otherwise if you post the machine driver and the kernel output with DEBUG enabled someone might be able to spot something.
On Monday 08 September 2008 21:51, you wrote:
On Mon, Sep 08, 2008 at 09:27:13PM +0100, Alan Horstmann wrote:
Attached and here inline is the small change we applied to ensure the byte order is correct in the _spi_write function. Note we observed the spi bus
I take it you're happy to give this your Signed-off-by?
Yes, fine, though obviously we haven't tested this with any other soc systems.
wm8731_spi_write_byte_order.patch
Ensure wm8731_spi_write byte order is consistent regardless of endianess.
Signed-off-by: Alan Horstmann gineera@aspect135.co.uk
With just this one change we have been successful in running the codec over spi. At present we do have an issue with dapm during capture -nothing is being turned on! Any pointers would be appreciated.
If you define DEBUG when building soc-dapm.c (a define at the top of the source file will do the trick) then it will be very verbose about the decisions it's making - that will normally point out the problem. Probably either one of the input controls is not configured to make a path from the input pins to the ADC or the input has been mistakenly marked as disabled.
Otherwise if you post the machine driver and the kernel output with DEBUG enabled someone might be able to spot something.
Thanks, Mark, we will try this.
Alan
wm8731_spi_write_byte_order.patch
--- wm8731-orig.c 2008-09-08 17:16:52.000000000 +0100 +++ wm8731.c 2008-09-08 21:03:16.000000000 +0100 @@ -688,12 +688,13 @@ { struct spi_transfer t; struct spi_message m; - u16 msg[2]; + u8 msg[2];
if (len <= 0) return 0;
- msg[0] = (data[0] << 8) + data[1]; + msg[0] = data[0]; + msg[1] = data[1];
spi_message_init(&m); memset(&t, 0, (sizeof t));
On Tue, 2008-09-09 at 09:45 +0100, Alan Horstmann wrote:
On Monday 08 September 2008 21:51, you wrote:
On Mon, Sep 08, 2008 at 09:27:13PM +0100, Alan Horstmann wrote:
Attached and here inline is the small change we applied to ensure the byte order is correct in the _spi_write function. Note we observed the spi bus
I take it you're happy to give this your Signed-off-by?
Yes, fine, though obviously we haven't tested this with any other soc systems.
wm8731_spi_write_byte_order.patch
Ensure wm8731_spi_write byte order is consistent regardless of endianess.
Signed-off-by: Alan Horstmann gineera@aspect135.co.uk
Might be worth rolling this out to other SPI capable codecs too.....
Liam
On Tue, Sep 09, 2008 at 10:03:58AM +0100, Liam Girdwood wrote:
Might be worth rolling this out to other SPI capable codecs too.....
Yeah, unfortunately it'll need to be done codec by codec checking the exact wire format required.
On Tue, 2008-09-09 at 10:35 +0100, Mark Brown wrote:
On Tue, Sep 09, 2008 at 10:03:58AM +0100, Liam Girdwood wrote:
Might be worth rolling this out to other SPI capable codecs too.....
Yeah, unfortunately it'll need to be done codec by codec checking the exact wire format required.
It will be same/similar per vendor/family (based on IP reuse).
Liam
On Tue, Sep 09, 2008 at 10:46:35AM +0100, Liam Girdwood wrote:
On Tue, 2008-09-09 at 10:35 +0100, Mark Brown wrote:
Yeah, unfortunately it'll need to be done codec by codec checking the exact wire format required.
It will be same/similar per vendor/family (based on IP reuse).
Oh, definitely - should just be a case of going through the devices and checking with their datasheets exactly what they expect.
At Mon, 1 Sep 2008 18:46:57 +0100, Mark Brown wrote:
The I2C layer uses I/O operations that aren't available on all architectures and since select bypasses Kconfig dependency checking selecting I2C breaks builds like allmodconfig on some architectures.
Signed-off-by: Mark Brown broonie@opensource.wolfsonmicro.com
Applied all 8 patches now. Thanks.
Note that the topic/asoc branch merged for-linus to include the previous fixes now.
Takashi
participants (6)
-
Alan Horstmann
-
Bryan Wu
-
Liam Girdwood
-
Mark Brown
-
Mark Brown
-
Takashi Iwai