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 return ret; 35 } 36 37 static int sigmadsp_read_i2c(void *control_data, 38 unsigned int addr, uint8_t data[], size_t len) 39 { 40 struct i2c_client *client = control_data; 41 struct i2c_msg msgs[2]; 42 uint8_t buf[2]; 43 int ret; 44 45 put_unaligned_be16(addr, buf); 46 47 msgs[0].addr = client->addr; 48 msgs[0].len = sizeof(buf); 49 msgs[0].buf = buf; 50 msgs[0].flags = 0; 51 52 msgs[1].addr = client->addr; 53 msgs[1].len = len; 54 msgs[1].buf = data; 55 msgs[1].flags = I2C_M_RD; 56 57 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); 58 if (ret < 0) 59 return ret; 60 else if (ret != ARRAY_SIZE(msgs)) 61 return -EIO; 62 return 0; 63 } 64 65 /** 66 * devm_sigmadsp_init_i2c() - Initialize SigmaDSP instance 67 * @client: The parent I2C device 68 * @ops: The sigmadsp_ops to use for this instance 69 * @firmware_name: Name of the firmware file to load 70 * 71 * Allocates a SigmaDSP instance and loads the specified firmware file. 72 * 73 * Returns a pointer to a struct sigmadsp on success, or a PTR_ERR() on error. 74 */ 75 struct sigmadsp *devm_sigmadsp_init_i2c(struct i2c_client *client, 76 const struct sigmadsp_ops *ops, const char *firmware_name) 77 { 78 struct sigmadsp *sigmadsp; 79 80 sigmadsp = devm_sigmadsp_init(&client->dev, ops, firmware_name); 81 if (IS_ERR(sigmadsp)) 82 return sigmadsp; 83 84 sigmadsp->control_data = client; 85 sigmadsp->write = sigmadsp_write_i2c; 86 sigmadsp->read = sigmadsp_read_i2c; 87 88 return sigmadsp; 89 } 90 EXPORT_SYMBOL_GPL(devm_sigmadsp_init_i2c); 91 92 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 93 MODULE_DESCRIPTION("SigmaDSP I2C firmware loader"); 94 MODULE_LICENSE("GPL"); 95