]>
git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - drivers/staging/media/atomisp/i2c/libmsrlisthelper.c
2 * Copyright (c) 2013 Intel Corporation. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License version
6 * 2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 #include <linux/i2c.h>
20 #include <linux/firmware.h>
21 #include <linux/device.h>
22 #include <linux/export.h>
23 #include <linux/libmsrlisthelper.h>
24 #include <linux/module.h>
25 #include <linux/slab.h>
27 /* Tagged binary data container structure definitions. */
29 uint32_t tag
; /*!< Tag identifier, also checks endianness */
30 uint32_t size
; /*!< Container size including this header */
31 uint32_t version
; /*!< Version, format 0xYYMMDDVV */
32 uint32_t revision
; /*!< Revision, format 0xYYMMDDVV */
33 uint32_t config_bits
; /*!< Configuration flag bits set */
34 uint32_t checksum
; /*!< Global checksum, header included */
37 struct tbd_record_header
{
38 uint32_t size
; /*!< Size of record including header */
39 uint8_t format_id
; /*!< tbd_format_t enumeration values used */
40 uint8_t packing_key
; /*!< Packing method; 0 = no packing */
41 uint16_t class_id
; /*!< tbd_class_t enumeration values used */
44 struct tbd_data_record_header
{
51 #define TBD_CLASS_DRV_ID 2
53 static int set_msr_configuration(struct i2c_client
*client
, uint8_t *bufptr
,
56 /* The configuration data contains any number of sequences where
57 * the first byte (that is, uint8_t) that marks the number of bytes
58 * in the sequence to follow, is indeed followed by the indicated
59 * number of bytes of actual data to be written to sensor.
60 * By convention, the first two bytes of actual data should be
61 * understood as an address in the sensor address space (hibyte
62 * followed by lobyte) where the remaining data in the sequence
65 uint8_t *ptr
= bufptr
;
66 while (ptr
< bufptr
+ size
) {
67 struct i2c_msg msg
= {
75 /* Where the bytes are located */
79 if (ptr
> bufptr
+ size
)
80 /* Accessing data beyond bounds is not tolerated */
83 ret
= i2c_transfer(client
->adapter
, &msg
, 1);
85 dev_err(&client
->dev
, "i2c write error: %d", ret
);
92 static int parse_and_apply(struct i2c_client
*client
, uint8_t *buffer
,
95 uint8_t *endptr8
= buffer
+ size
;
96 struct tbd_data_record_header
*header
=
97 (struct tbd_data_record_header
*)buffer
;
99 /* There may be any number of datasets present */
100 unsigned int dataset
= 0;
103 /* In below, four variables are read from buffer */
104 if ((uint8_t *)header
+ sizeof(*header
) > endptr8
)
107 /* All data should be located within given buffer */
108 if ((uint8_t *)header
+ header
->data_offset
+
109 header
->data_size
> endptr8
)
112 /* We have a new valid dataset */
114 /* See whether there is MSR data */
115 /* If yes, update the reg info */
116 if (header
->data_size
&& (header
->flags
& 1)) {
119 dev_info(&client
->dev
,
120 "New MSR data for sensor driver (dataset %02d) size:%d\n",
121 dataset
, header
->data_size
);
122 ret
= set_msr_configuration(client
,
123 buffer
+ header
->data_offset
,
128 header
= (struct tbd_data_record_header
*)(buffer
+
129 header
->next_offset
);
130 } while (header
->next_offset
);
135 int apply_msr_data(struct i2c_client
*client
, const struct firmware
*fw
)
137 struct tbd_header
*header
;
138 struct tbd_record_header
*record
;
141 dev_warn(&client
->dev
, "Drv data is not loaded.\n");
145 if (sizeof(*header
) > fw
->size
)
148 header
= (struct tbd_header
*)fw
->data
;
149 /* Check that we have drvb block. */
150 if (memcmp(&header
->tag
, "DRVB", 4))
154 if (header
->size
!= fw
->size
)
157 if (sizeof(*header
) + sizeof(*record
) > fw
->size
)
160 record
= (struct tbd_record_header
*)(header
+ 1);
161 /* Check that class id mathes tbd's drv id. */
162 if (record
->class_id
!= TBD_CLASS_DRV_ID
)
165 /* Size 0 shall not be treated as an error */
169 return parse_and_apply(client
, (uint8_t *)(record
+ 1), record
->size
);
171 EXPORT_SYMBOL_GPL(apply_msr_data
);
173 int load_msr_list(struct i2c_client
*client
, char *name
,
174 const struct firmware
**fw
)
176 int ret
= request_firmware(fw
, name
, &client
->dev
);
178 dev_err(&client
->dev
,
179 "Error %d while requesting firmware %s\n",
183 dev_info(&client
->dev
, "Received %lu bytes drv data\n",
184 (unsigned long)(*fw
)->size
);
188 EXPORT_SYMBOL_GPL(load_msr_list
);
190 void release_msr_list(struct i2c_client
*client
, const struct firmware
*fw
)
192 release_firmware(fw
);
194 EXPORT_SYMBOL_GPL(release_msr_list
);
196 static int init_msrlisthelper(void)
201 static void exit_msrlisthelper(void)
205 module_init(init_msrlisthelper
);
206 module_exit(exit_msrlisthelper
);
208 MODULE_AUTHOR("Jukka Kaartinen <jukka.o.kaartinen@intel.com>");
209 MODULE_LICENSE("GPL");