1 /* 2 * Load Analog Devices SigmaStudio firmware files 3 * 4 * Copyright 2009-2011 Analog Devices Inc. 5 * 6 * Licensed under the GPL-2 or later. 7 */ 8 9 #include <linux/export.h> 10 #include <linux/i2c.h> 11 #include <linux/module.h> 12 #include <linux/slab.h> 13 #include <asm/unaligned.h> 14 15 #include "sigmadsp.h" 16 17 static int sigmadsp_write_i2c(void *control_data, 18 unsigned int addr, const uint8_t data[], size_t len) 19 { 20 uint8_t *buf; 21 int ret; 22 23 buf = kzalloc(2 + len, GFP_KERNEL | GFP_DMA); 24 if (!buf) 25 return -ENOMEM; 26 27 put_unaligned_be16(addr, buf); 28 memcpy(buf + 2, data, len); 29 30 ret = i2c_master_send(control_data, buf, len + 2); 31 32 kfree(buf); 33 34 if (ret < 0) 35 return ret; 36 37 return 0; 38 } 39 40 static int sigmadsp_read_i2c(void *control_data, 41 unsigned int addr, uint8_t data[], size_t len) 42 { 43 struct i2c_client *client = control_data; 44 struct i2c_msg msgs[2]; 45 uint8_t buf[2]; 46 int ret; 47 48 put_unaligned_be16(addr, buf); 49 50 msgs[0].addr = client->addr; 51 msgs[0].len = sizeof(buf); 52 msgs[0].buf = buf; 53 msgs[0].flags = 0; 54 55 msgs[1].addr = client->addr; 56 msgs[1].len = len; 57 msgs[1].buf = data; 58 msgs[1].flags = I2C_M_RD; 59 60 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); 61 if (ret < 0) 62 return ret; 63 else if (ret != ARRAY_SIZE(msgs)) 64 return -EIO; 65 return 0; 66 } 67 68 /** 69 * devm_sigmadsp_init_i2c() - Initialize SigmaDSP instance 70 * @client: The parent I2C device 71 * @ops: The sigmadsp_ops to use for this instance 72 * @firmware_name: Name of the firmware file to load 73 * 74 * Allocates a SigmaDSP instance and loads the specified firmware file. 75 * 76 * Returns a pointer to a struct sigmadsp on success, or a PTR_ERR() on error. 77 */ 78 struct sigmadsp *devm_sigmadsp_init_i2c(struct i2c_client *client, 79 const struct sigmadsp_ops *ops, const char *firmware_name) 80 { 81 struct sigmadsp *sigmadsp; 82 83 sigmadsp = devm_sigmadsp_init(&client->dev, ops, firmware_name); 84 if (IS_ERR(sigmadsp)) 85 return sigmadsp; 86 87 sigmadsp->control_data = client; 88 sigmadsp->write = sigmadsp_write_i2c; 89 sigmadsp->read = sigmadsp_read_i2c; 90 91 return sigmadsp; 92 } 93 EXPORT_SYMBOL_GPL(devm_sigmadsp_init_i2c); 94 95 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 96 MODULE_DESCRIPTION("SigmaDSP I2C firmware loader"); 97 MODULE_LICENSE("GPL"); 98