diff options
author | Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> | 2012-04-22 08:11:26 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-05-20 11:45:39 -0400 |
commit | ceb9e30e9f4a892997a61f1f5a30bc5b561c9e67 (patch) | |
tree | e11eaabf3ac03008cceab8f1abf2732349c9ba64 /drivers/media/video | |
parent | 1e73eea781bc302ba7f35da89d627bd355a7814a (diff) |
[media] smiapp: Quirk for sensors that only do 8-bit reads
Some sensors implement only 8-bit read functionality and fail on wider
reads. Add a quirk flag for such sensors.
Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video')
-rw-r--r-- | drivers/media/video/smiapp/smiapp-quirk.h | 1 | ||||
-rw-r--r-- | drivers/media/video/smiapp/smiapp-regs.c | 73 | ||||
-rw-r--r-- | drivers/media/video/smiapp/smiapp-regs.h | 1 |
3 files changed, 66 insertions, 9 deletions
diff --git a/drivers/media/video/smiapp/smiapp-quirk.h b/drivers/media/video/smiapp/smiapp-quirk.h index 7a1b3a02a7bd..de82cdf43a89 100644 --- a/drivers/media/video/smiapp/smiapp-quirk.h +++ b/drivers/media/video/smiapp/smiapp-quirk.h | |||
@@ -46,6 +46,7 @@ struct smiapp_quirk { | |||
46 | 46 | ||
47 | /* op pix clock is for all lanes in total normally */ | 47 | /* op pix clock is for all lanes in total normally */ |
48 | #define SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE (1 << 0) | 48 | #define SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE (1 << 0) |
49 | #define SMIAPP_QUIRK_FLAG_8BIT_READ_ONLY (1 << 1) | ||
49 | 50 | ||
50 | struct smiapp_reg_8 { | 51 | struct smiapp_reg_8 { |
51 | u16 reg; | 52 | u16 reg; |
diff --git a/drivers/media/video/smiapp/smiapp-regs.c b/drivers/media/video/smiapp/smiapp-regs.c index e5e5f4356dd2..9c430647b047 100644 --- a/drivers/media/video/smiapp/smiapp-regs.c +++ b/drivers/media/video/smiapp/smiapp-regs.c | |||
@@ -78,19 +78,15 @@ static uint32_t float_to_u32_mul_1000000(struct i2c_client *client, | |||
78 | * Read a 8/16/32-bit i2c register. The value is returned in 'val'. | 78 | * Read a 8/16/32-bit i2c register. The value is returned in 'val'. |
79 | * Returns zero if successful, or non-zero otherwise. | 79 | * Returns zero if successful, or non-zero otherwise. |
80 | */ | 80 | */ |
81 | int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val) | 81 | static int ____smiapp_read(struct smiapp_sensor *sensor, u16 reg, |
82 | u16 len, u32 *val) | ||
82 | { | 83 | { |
83 | struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); | 84 | struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); |
84 | struct i2c_msg msg; | 85 | struct i2c_msg msg; |
85 | unsigned char data[4]; | 86 | unsigned char data[4]; |
86 | unsigned int len = (u8)(reg >> 16); | ||
87 | u16 offset = reg; | 87 | u16 offset = reg; |
88 | int r; | 88 | int r; |
89 | 89 | ||
90 | if (len != SMIA_REG_8BIT && len != SMIA_REG_16BIT | ||
91 | && len != SMIA_REG_32BIT) | ||
92 | return -EINVAL; | ||
93 | |||
94 | msg.addr = client->addr; | 90 | msg.addr = client->addr; |
95 | msg.flags = 0; | 91 | msg.flags = 0; |
96 | msg.len = 2; | 92 | msg.len = 2; |
@@ -132,9 +128,6 @@ int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val) | |||
132 | BUG(); | 128 | BUG(); |
133 | } | 129 | } |
134 | 130 | ||
135 | if (reg & SMIA_REG_FLAG_FLOAT) | ||
136 | *val = float_to_u32_mul_1000000(client, *val); | ||
137 | |||
138 | return 0; | 131 | return 0; |
139 | 132 | ||
140 | err: | 133 | err: |
@@ -143,6 +136,68 @@ err: | |||
143 | return r; | 136 | return r; |
144 | } | 137 | } |
145 | 138 | ||
139 | /* Read a register using 8-bit access only. */ | ||
140 | static int ____smiapp_read_8only(struct smiapp_sensor *sensor, u16 reg, | ||
141 | u16 len, u32 *val) | ||
142 | { | ||
143 | unsigned int i; | ||
144 | int rval; | ||
145 | |||
146 | *val = 0; | ||
147 | |||
148 | for (i = 0; i < len; i++) { | ||
149 | u32 val8; | ||
150 | |||
151 | rval = ____smiapp_read(sensor, reg + i, 1, &val8); | ||
152 | if (rval < 0) | ||
153 | return rval; | ||
154 | *val |= val8 << ((len - i - 1) << 3); | ||
155 | } | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | /* | ||
161 | * Read a 8/16/32-bit i2c register. The value is returned in 'val'. | ||
162 | * Returns zero if successful, or non-zero otherwise. | ||
163 | */ | ||
164 | static int __smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val, | ||
165 | bool only8) | ||
166 | { | ||
167 | struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); | ||
168 | unsigned int len = (u8)(reg >> 16); | ||
169 | int rval; | ||
170 | |||
171 | if (len != SMIA_REG_8BIT && len != SMIA_REG_16BIT | ||
172 | && len != SMIA_REG_32BIT) | ||
173 | return -EINVAL; | ||
174 | |||
175 | if (len == SMIA_REG_8BIT && !only8) | ||
176 | rval = ____smiapp_read(sensor, (u16)reg, len, val); | ||
177 | else | ||
178 | rval = ____smiapp_read_8only(sensor, (u16)reg, len, val); | ||
179 | if (rval < 0) | ||
180 | return rval; | ||
181 | |||
182 | if (reg & SMIA_REG_FLAG_FLOAT) | ||
183 | *val = float_to_u32_mul_1000000(client, *val); | ||
184 | |||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val) | ||
189 | { | ||
190 | return __smiapp_read( | ||
191 | sensor, reg, val, | ||
192 | smiapp_needs_quirk(sensor, | ||
193 | SMIAPP_QUIRK_FLAG_8BIT_READ_ONLY)); | ||
194 | } | ||
195 | |||
196 | int smiapp_read_8only(struct smiapp_sensor *sensor, u32 reg, u32 *val) | ||
197 | { | ||
198 | return __smiapp_read(sensor, reg, val, true); | ||
199 | } | ||
200 | |||
146 | /* | 201 | /* |
147 | * Write to a 8/16-bit register. | 202 | * Write to a 8/16-bit register. |
148 | * Returns zero if successful, or non-zero otherwise. | 203 | * Returns zero if successful, or non-zero otherwise. |
diff --git a/drivers/media/video/smiapp/smiapp-regs.h b/drivers/media/video/smiapp/smiapp-regs.h index 1edfd206fb76..7f9013b47971 100644 --- a/drivers/media/video/smiapp/smiapp-regs.h +++ b/drivers/media/video/smiapp/smiapp-regs.h | |||
@@ -43,6 +43,7 @@ struct smia_reg { | |||
43 | struct smiapp_sensor; | 43 | struct smiapp_sensor; |
44 | 44 | ||
45 | int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val); | 45 | int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val); |
46 | int smiapp_read_8only(struct smiapp_sensor *sensor, u32 reg, u32 *val); | ||
46 | int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val); | 47 | int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val); |
47 | 48 | ||
48 | #endif | 49 | #endif |