| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * drivers/media/i2c/smiapp/smiapp-regs.c |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 5 | 6 | * |
|---|
| 6 | 7 | * Copyright (C) 2011--2012 Nokia Corporation |
|---|
| 7 | 8 | * Contact: Sakari Ailus <sakari.ailus@iki.fi> |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is free software; you can redistribute it and/or |
|---|
| 10 | | - * modify it under the terms of the GNU General Public License |
|---|
| 11 | | - * version 2 as published by the Free Software Foundation. |
|---|
| 12 | | - * |
|---|
| 13 | | - * This program is distributed in the hope that it will be useful, but |
|---|
| 14 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 15 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|---|
| 16 | | - * General Public License for more details. |
|---|
| 17 | 9 | */ |
|---|
| 10 | + |
|---|
| 11 | +#include <asm/unaligned.h> |
|---|
| 18 | 12 | |
|---|
| 19 | 13 | #include <linux/delay.h> |
|---|
| 20 | 14 | #include <linux/i2c.h> |
|---|
| .. | .. |
|---|
| 77 | 71 | { |
|---|
| 78 | 72 | struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); |
|---|
| 79 | 73 | struct i2c_msg msg; |
|---|
| 80 | | - unsigned char data[4]; |
|---|
| 81 | | - u16 offset = reg; |
|---|
| 74 | + unsigned char data_buf[sizeof(u32)] = { 0 }; |
|---|
| 75 | + unsigned char offset_buf[sizeof(u16)]; |
|---|
| 82 | 76 | int r; |
|---|
| 77 | + |
|---|
| 78 | + if (len > sizeof(data_buf)) |
|---|
| 79 | + return -EINVAL; |
|---|
| 83 | 80 | |
|---|
| 84 | 81 | msg.addr = client->addr; |
|---|
| 85 | 82 | msg.flags = 0; |
|---|
| 86 | | - msg.len = 2; |
|---|
| 87 | | - msg.buf = data; |
|---|
| 83 | + msg.len = sizeof(offset_buf); |
|---|
| 84 | + msg.buf = offset_buf; |
|---|
| 85 | + put_unaligned_be16(reg, offset_buf); |
|---|
| 88 | 86 | |
|---|
| 89 | | - /* high byte goes out first */ |
|---|
| 90 | | - data[0] = (u8) (offset >> 8); |
|---|
| 91 | | - data[1] = (u8) offset; |
|---|
| 92 | 87 | r = i2c_transfer(client->adapter, &msg, 1); |
|---|
| 93 | 88 | if (r != 1) { |
|---|
| 94 | 89 | if (r >= 0) |
|---|
| .. | .. |
|---|
| 98 | 93 | |
|---|
| 99 | 94 | msg.len = len; |
|---|
| 100 | 95 | msg.flags = I2C_M_RD; |
|---|
| 96 | + msg.buf = &data_buf[sizeof(data_buf) - len]; |
|---|
| 97 | + |
|---|
| 101 | 98 | r = i2c_transfer(client->adapter, &msg, 1); |
|---|
| 102 | 99 | if (r != 1) { |
|---|
| 103 | 100 | if (r >= 0) |
|---|
| .. | .. |
|---|
| 105 | 102 | goto err; |
|---|
| 106 | 103 | } |
|---|
| 107 | 104 | |
|---|
| 108 | | - *val = 0; |
|---|
| 109 | | - /* high byte comes first */ |
|---|
| 110 | | - switch (len) { |
|---|
| 111 | | - case SMIAPP_REG_32BIT: |
|---|
| 112 | | - *val = (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + |
|---|
| 113 | | - data[3]; |
|---|
| 114 | | - break; |
|---|
| 115 | | - case SMIAPP_REG_16BIT: |
|---|
| 116 | | - *val = (data[0] << 8) + data[1]; |
|---|
| 117 | | - break; |
|---|
| 118 | | - case SMIAPP_REG_8BIT: |
|---|
| 119 | | - *val = data[0]; |
|---|
| 120 | | - break; |
|---|
| 121 | | - default: |
|---|
| 122 | | - BUG(); |
|---|
| 123 | | - } |
|---|
| 105 | + *val = get_unaligned_be32(data_buf); |
|---|
| 124 | 106 | |
|---|
| 125 | 107 | return 0; |
|---|
| 126 | 108 | |
|---|
| 127 | 109 | err: |
|---|
| 128 | | - dev_err(&client->dev, "read from offset 0x%x error %d\n", offset, r); |
|---|
| 110 | + dev_err(&client->dev, "read from offset 0x%x error %d\n", reg, r); |
|---|
| 129 | 111 | |
|---|
| 130 | 112 | return r; |
|---|
| 131 | 113 | } |
|---|
| .. | .. |
|---|
| 166 | 148 | && len != SMIAPP_REG_32BIT) |
|---|
| 167 | 149 | return -EINVAL; |
|---|
| 168 | 150 | |
|---|
| 169 | | - if (len == SMIAPP_REG_8BIT || !only8) |
|---|
| 151 | + if (!only8) |
|---|
| 170 | 152 | rval = ____smiapp_read(sensor, SMIAPP_REG_ADDR(reg), len, val); |
|---|
| 171 | 153 | else |
|---|
| 172 | 154 | rval = ____smiapp_read_8only(sensor, SMIAPP_REG_ADDR(reg), len, |
|---|
| .. | .. |
|---|
| 222 | 204 | struct i2c_msg msg; |
|---|
| 223 | 205 | unsigned char data[6]; |
|---|
| 224 | 206 | unsigned int retries; |
|---|
| 225 | | - u8 flags = SMIAPP_REG_FLAGS(reg); |
|---|
| 226 | 207 | u8 len = SMIAPP_REG_WIDTH(reg); |
|---|
| 227 | | - u16 offset = SMIAPP_REG_ADDR(reg); |
|---|
| 228 | 208 | int r; |
|---|
| 229 | 209 | |
|---|
| 230 | | - if ((len != SMIAPP_REG_8BIT && len != SMIAPP_REG_16BIT && |
|---|
| 231 | | - len != SMIAPP_REG_32BIT) || flags) |
|---|
| 210 | + if (len > sizeof(data) - 2) |
|---|
| 232 | 211 | return -EINVAL; |
|---|
| 233 | | - |
|---|
| 234 | | - if (!sensor->active) |
|---|
| 235 | | - return 0; |
|---|
| 236 | 212 | |
|---|
| 237 | 213 | msg.addr = client->addr; |
|---|
| 238 | 214 | msg.flags = 0; /* Write */ |
|---|
| 239 | 215 | msg.len = 2 + len; |
|---|
| 240 | 216 | msg.buf = data; |
|---|
| 241 | 217 | |
|---|
| 242 | | - /* high byte goes out first */ |
|---|
| 243 | | - data[0] = (u8) (reg >> 8); |
|---|
| 244 | | - data[1] = (u8) (reg & 0xff); |
|---|
| 245 | | - |
|---|
| 246 | | - switch (len) { |
|---|
| 247 | | - case SMIAPP_REG_8BIT: |
|---|
| 248 | | - data[2] = val; |
|---|
| 249 | | - break; |
|---|
| 250 | | - case SMIAPP_REG_16BIT: |
|---|
| 251 | | - data[2] = val >> 8; |
|---|
| 252 | | - data[3] = val; |
|---|
| 253 | | - break; |
|---|
| 254 | | - case SMIAPP_REG_32BIT: |
|---|
| 255 | | - data[2] = val >> 24; |
|---|
| 256 | | - data[3] = val >> 16; |
|---|
| 257 | | - data[4] = val >> 8; |
|---|
| 258 | | - data[5] = val; |
|---|
| 259 | | - break; |
|---|
| 260 | | - default: |
|---|
| 261 | | - BUG(); |
|---|
| 262 | | - } |
|---|
| 218 | + put_unaligned_be16(SMIAPP_REG_ADDR(reg), data); |
|---|
| 219 | + put_unaligned_be32(val << (8 * (sizeof(val) - len)), data + 2); |
|---|
| 263 | 220 | |
|---|
| 264 | 221 | for (retries = 0; retries < 5; retries++) { |
|---|
| 265 | 222 | /* |
|---|
| .. | .. |
|---|
| 280 | 237 | } |
|---|
| 281 | 238 | |
|---|
| 282 | 239 | dev_err(&client->dev, |
|---|
| 283 | | - "wrote 0x%x to offset 0x%x error %d\n", val, offset, r); |
|---|
| 240 | + "wrote 0x%x to offset 0x%x error %d\n", val, |
|---|
| 241 | + SMIAPP_REG_ADDR(reg), r); |
|---|
| 284 | 242 | |
|---|
| 285 | 243 | return r; |
|---|
| 286 | 244 | } |
|---|