]>
git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/staging/media/atomisp/i2c/atomisp-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.
15 #include <linux/i2c.h>
16 #include <linux/firmware.h>
17 #include <linux/device.h>
18 #include <linux/export.h>
19 #include "../include/linux/libmsrlisthelper.h"
20 #include <linux/module.h>
21 #include <linux/slab.h>
23 /* Tagged binary data container structure definitions. */
25 uint32_t tag
; /*!< Tag identifier, also checks endianness */
26 uint32_t size
; /*!< Container size including this header */
27 uint32_t version
; /*!< Version, format 0xYYMMDDVV */
28 uint32_t revision
; /*!< Revision, format 0xYYMMDDVV */
29 uint32_t config_bits
; /*!< Configuration flag bits set */
30 uint32_t checksum
; /*!< Global checksum, header included */
33 struct tbd_record_header
{
34 uint32_t size
; /*!< Size of record including header */
35 uint8_t format_id
; /*!< tbd_format_t enumeration values used */
36 uint8_t packing_key
; /*!< Packing method; 0 = no packing */
37 uint16_t class_id
; /*!< tbd_class_t enumeration values used */
40 struct tbd_data_record_header
{
47 #define TBD_CLASS_DRV_ID 2
49 static int set_msr_configuration(struct i2c_client
*client
, uint8_t *bufptr
,
52 /* The configuration data contains any number of sequences where
53 * the first byte (that is, uint8_t) that marks the number of bytes
54 * in the sequence to follow, is indeed followed by the indicated
55 * number of bytes of actual data to be written to sensor.
56 * By convention, the first two bytes of actual data should be
57 * understood as an address in the sensor address space (hibyte
58 * followed by lobyte) where the remaining data in the sequence
61 uint8_t *ptr
= bufptr
;
62 while (ptr
< bufptr
+ size
) {
63 struct i2c_msg msg
= {
71 /* Where the bytes are located */
75 if (ptr
> bufptr
+ size
)
76 /* Accessing data beyond bounds is not tolerated */
79 ret
= i2c_transfer(client
->adapter
, &msg
, 1);
81 dev_err(&client
->dev
, "i2c write error: %d", ret
);
88 static int parse_and_apply(struct i2c_client
*client
, uint8_t *buffer
,
91 uint8_t *endptr8
= buffer
+ size
;
92 struct tbd_data_record_header
*header
=
93 (struct tbd_data_record_header
*)buffer
;
95 /* There may be any number of datasets present */
96 unsigned int dataset
= 0;
99 /* In below, four variables are read from buffer */
100 if ((uint8_t *)header
+ sizeof(*header
) > endptr8
)
103 /* All data should be located within given buffer */
104 if ((uint8_t *)header
+ header
->data_offset
+
105 header
->data_size
> endptr8
)
108 /* We have a new valid dataset */
110 /* See whether there is MSR data */
111 /* If yes, update the reg info */
112 if (header
->data_size
&& (header
->flags
& 1)) {
115 dev_info(&client
->dev
,
116 "New MSR data for sensor driver (dataset %02d) size:%d\n",
117 dataset
, header
->data_size
);
118 ret
= set_msr_configuration(client
,
119 buffer
+ header
->data_offset
,
124 header
= (struct tbd_data_record_header
*)(buffer
+
125 header
->next_offset
);
126 } while (header
->next_offset
);
131 int apply_msr_data(struct i2c_client
*client
, const struct firmware
*fw
)
133 struct tbd_header
*header
;
134 struct tbd_record_header
*record
;
137 dev_warn(&client
->dev
, "Drv data is not loaded.\n");
141 if (sizeof(*header
) > fw
->size
)
144 header
= (struct tbd_header
*)fw
->data
;
145 /* Check that we have drvb block. */
146 if (memcmp(&header
->tag
, "DRVB", 4))
150 if (header
->size
!= fw
->size
)
153 if (sizeof(*header
) + sizeof(*record
) > fw
->size
)
156 record
= (struct tbd_record_header
*)(header
+ 1);
157 /* Check that class id mathes tbd's drv id. */
158 if (record
->class_id
!= TBD_CLASS_DRV_ID
)
161 /* Size 0 shall not be treated as an error */
165 return parse_and_apply(client
, (uint8_t *)(record
+ 1), record
->size
);
167 EXPORT_SYMBOL_GPL(apply_msr_data
);
169 int load_msr_list(struct i2c_client
*client
, char *name
,
170 const struct firmware
**fw
)
172 int ret
= request_firmware(fw
, name
, &client
->dev
);
174 dev_err(&client
->dev
,
175 "Error %d while requesting firmware %s\n",
179 dev_info(&client
->dev
, "Received %lu bytes drv data\n",
180 (unsigned long)(*fw
)->size
);
184 EXPORT_SYMBOL_GPL(load_msr_list
);
186 void release_msr_list(struct i2c_client
*client
, const struct firmware
*fw
)
188 release_firmware(fw
);
190 EXPORT_SYMBOL_GPL(release_msr_list
);
192 static int init_msrlisthelper(void)
197 static void exit_msrlisthelper(void)
201 module_init(init_msrlisthelper
);
202 module_exit(exit_msrlisthelper
);
204 MODULE_AUTHOR("Jukka Kaartinen <jukka.o.kaartinen@intel.com>");
205 MODULE_LICENSE("GPL");